Search code examples
ruby-on-rails-5nested-formscocoon-gem

Nested Attributes - Cocoon Gem - form_for “First argument in form cannot contain nil or be empty” - Rails 5


This is an oldie but goldie, therefore I am really sorry for asking, but after checking 10+ posts with the similar errors, I still had no luck so far.

Attempting to use a "form for" to get nested forms to work with the help of the Cocoon gem.

Though I am getting the "First argument in form cannot contain nil or be empty" error.

Here is the _text_form partial.html.erb :

<%= form_for(@text, html: { multipart: true }) do |f| %>
 <%= render 'shared/error_messages', object: f.object %>
 <div class="field">
  <%= f.text_field :title, placeholder: "Enter Title" %>
  <%= f.text_field :publication, placeholder: "Enter Publication" %>
  <%= f.text_field :author, placeholder: "Enter Author" %>
  <%= f.text_field :url, placeholder: "Enter Url" %> 
 </div>
 <div>
  <h3>Quotes:</h3>
  <div id="quotes">
    <%= f.fields_for :quotes do |quote| %>
      <%= render 'shared/quote_fields', f: quote %>
    <% end %>

   <div class="links">
     <%= link_to_add_association 'add quote', f, :quotes, class: "btn btn-default" %>
   </div>
  </div>
 </div>


 <%= f.submit "Post", class: "btn btn-primary" %>
<% end %>

This is the _quotes_fields.html.erb partial:

<div class="nested-fields">
 <%= f.text_area :content, placeholder: "Compose new quote..." %>
 <span class="picture">
  <%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
 </span>
 <%= link_to_remove_association "remove quote", f, class: "btn btn-default" %>
</div>

<script type="text/javascript">
  $('#quote_picture').bind('change', function() {
   var size_in_megabytes = this.files[0].size/1024/1024;
   if (size_in_megabytes > 2) {
     alert('Maximum file size is 2MB. Please choose a smaller file.');
   }
  });
</script>

This is the texts_controller.rb:

class TextsController < ApplicationController

 before_action :logged_in_user, only: [:create, :edit, :update, :destroy]
 before_action :correct_user, only: :destroy
 before_action :find_text, only: [:show, :edit, :update, :destroy]



 def show
 end

 def new
  @text = current_user.texts.build
 end

 def create
  @text = current_user.texts.build(text_params)
  if @text.save
   flash[:success] = "Text created!"
   redirect_to root_url
  else
   render 'static_pages/home'
  end
 end


 def edit
 end

 def update
  if @text.update(text_params)
   redirect_to @text
  else
  render 'edit'
  end
 end

 def destroy
  @text.destroy
  flash[:success] = "Text deleted"
  redirect_to request.referrer || root_url
 end

private

 def text_params
  params.require(:text).permit(:url, :title, :coverimage,
                              :publication, :author, :summary, quotes_attributes: [:id, :content, :picture, :_destroy])
 end

 def find_text
    @text = Text.find(params[:id])
 end

 def correct_user
  @user = User.find(params[:id])
  redirect_to(root_url) unless current_user?(@user)
 end

end

Sorry upfront, if there are any easy horrifying newbie mistakes and thanks so much for helping out.

Update: The _text_form partial is rendered in ../static_pages/home.html.erb

Update 2: This is the routes.rb:

Rails.application.routes.draw do

 get 'password_resets/new'

 get 'password_resets/edit'

 get 'sessions/new'

 root           'static_pages#home'
 get 'help'  => 'static_pages#help'
 get 'about' => 'static_pages#about'
 get 'signup' => 'users#new'
 get 'login' => 'sessions#new'
 post 'login' => 'sessions#create'
 delete 'logout' => 'sessions#destroy'
 resources :users do
  member do
   get :following, :followers
  end
 end
 resources :account_activations, only: [:edit]
 resources :password_resets, only: [:new, :create, :edit, :update]
 resources :quotes, only: [:create, :destroy]
 resources :texts, only: [:new, :create, :edit, :update]
 resources :relationships, only: [:create, :destroy]
 end

Solution

  • This error happens because @text is not defined yet, so you just need to define it in action which you will render your partial, in this case is your home action in your static pages controller.