Topic: Help with form_for and collection_select

I'm coming across an error when trying to use form_for with collection_select:

I've got a few models:

class Company
    has_many :services
    has_many :projects
end

class Service
    belongs_to :projects
    belongs_to :companies
end

class Project
    has_many :services
    belongs_to :companies
end


Also using restful routes:

map.resources :companies , :has_many => [:projects, :services]

I'm creating a new service at /companies/1/services/new with form_for and I'm using collection_select to provide a dropdown list of projects:

<% form_for([@company, @service]) do |f| %>

    <%= f.collection_select(:service, :project_id , @projects, :id, :name, {:prompt => true}) %>


    ..............etc

<% end %>


... which results in the following error:

undefined method `merge' for :name:Symbol

When I try the same thing with form_tag instead of form_for the list is rendered without a problem.

Can anyone see what I'm doing wrong?

Thanks for any help.

Re: Help with form_for and collection_select

Collection select looks like this:

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

You have this:
<%= f.collection_select(:service, :project_id , @projects, :id, :name, {:prompt => true}) %>

1) f is the object in this case
2) you have service as the object too but it is being treated as the method since f is the object already

You need to choose between f.collection_select(:project_id .....) and collection_select(:service, :project_id .... probably like:

<%= collection_select(:service, :project_id , @projects, :id, :name, {:prompt => true}) %>

Last edited by pullmonkey (2008-02-07 19:36:45)

Re: Help with form_for and collection_select

I had this same problem pullmonkey, thanks for the help, that gave me a populated field list but I think there is some code missing to submit the field value, my error is:

Mysql::Error: #23000Column 'category_name' cannot be null: INSERT INTO `tasks` (`created_on`, `category_name`, `note_id`, `done`, `private`, `updated_on`, `priority`, `description`, `due_date`, `user_id`) VALUES('2008-05-09 14:37:36', NULL, NULL, 0, 0, '2008-05-09 14:37:36', 0, '', NULL, 1)

My code:

<%=
    @categories = Category.find(:all, :order => "name")
    collection_select(:category, :category_id, @categories, :id, :name)
%>


Thanks for any help.

Last edited by acdcwebs (2008-05-09 14:56:49)

Re: Help with form_for and collection_select

Your task model is requiring a category_name and you are passing a category_id in the form. 

Try this instead:
collection_select(:category, :category_name, @categories, :name, :name)

or change your task to have a category_id, which would be better.

Re: Help with form_for and collection_select

Thanks, that makes perfect sense but for some reason it still doesn't take. Is there other code needed to pass the variable selected from the list or does this code do it by itself. I will try changing to category_id, not sure why I had it as category_name to begin with.

Also, submissions were working fine before with just a text field.

Re: Help with form_for and collection_select

Can you post the generated html and your submitting action?

Re: Help with form_for and collection_select

Here is the entire form, generated html below:

<div id="theform">
<% form_for :task do |f| %>
<fieldset>
    <legend>Add a Task</legend>
   
<p><label>Project: <br /></label>

    <%=
        @categories = Category.find(:all, :order => "name")
        collection_select(:category, :category_name, @categories, :name, :name)
    %>


<p><label>Assign to: <br /></label>

<%=
     @users = User.find(:all, :order => "name")
     collection_select(:task, :user_id, @users, :id, :name)
%>


<p><label>Description: <br /></label>
   
  <%= f.text_area :description %>

<strong>
    <%= submit_tag %>
<strong>
    </fieldset>


HTML:

<select id="category_category_name" name="category[category_name]"><option value="Balls">Balls</option>
<option value="Ocean One">Ocean One</option>
<option value="Ocean Three">Ocean Three</option>
<option value="Ocean Two">Ocean Two</option>
<option value="Porto Santo">Porto Santo</option>
<option value="Sea Breeze">Sea Breeze</option>
<option value="Show Room">Show Room</option></select>

Re: Help with form_for and collection_select

you want this I think:
collection_select(:task, :category_name, @categories, :name, :name)

Re: Help with form_for and collection_select

That was right, thanks again. I already had that set for the user selection:

<%=
     @users = User.find(:all, :order => "name")
     collection_select(:task, :user_id, @users, :id, :name)
%>

This is used to assign a task to another user by currently I can only get them to be assigned to me no matter what user name I choose:

HTML:

<select id="task_user_id" name="task[user_id]"><option value="1" selected="selected">Anthony</option>
<option value="2">Ethan</option>
<option value="3">Gavin</option>
<option value="4">Melissa</option>
<option value="5">Peter</option></select>

Here is a snippet from the controller:

def new
   @task = Task.new(params[:task])
   @task.user = @current_user

It looks like I need to change that last part: @current_user but I'm not sure what to.

Re: Help with form_for and collection_select

I guess that was a stupid question. I just removed the line @task.user = @current_user and it works.

Re: Help with form_for and collection_select

Hello pullmonkey.

YOu insight was helpful. I check the html code of my setup and realised that my method and values were incorrect. I finally did this in my view:

<p>
    <%= f.label :company %><br />
  <%= f.collection_select ( :company, Client.find(:all), :firstname, :firstname ) %>
</p>

My HTML code looks like this:

<p>
    <label for="ticket_company">Company</label><br />
  <select id="ticket_company" name="ticket[company]">
<option value="Redro">Redro</option>
<option value="Cortnie">Cortnie</option>
<option value="Zethan">Zethan</option>
<option value="Jack">Jack</option>
<option value="Jade">Jade</option>
<option value="Reggie">Reggie</option>
<option value="Nicola">Nicola</option></select>
</p>

(I know, I am using firstname for a company name, but I am still learning and will perfect it once I got the just of things.)

It goes something like this if explained:

<%= object.collection_select ( :method, collection, :value_method, :text_method ) %>

Basically I wanted to pull a list of contacts from a client list and throw it into another form as a drop down list so one could choose. The value and method are relevant to the database and field its pulling from, company is the field it will use to post to in the new column. The collection is what I want to retrieve from the database. You will see the select id="ticket_company" and name="ticket[company]", uses the controller (ticket) and the method (company) to create the form selection which it uses to post.Well, that's at least how I worked it out. (I may be incorrect in the , :firstname, :firstname ), but it works)

The :company was the new field in the form where I am using select and the column where the data must be placed in the database. Just for guidance, The old code made by the scaffold that I changed was:

<p>
    <%= f.label :company %><br />
    <%= f.text_field :company %>
  </p>

It worked for me, hopefully someone ,looking for help finds it here as well. I am a absolute newbie to ruby and rails so its one of my best achievements to date. Cool!!

Gigg

Last edited by gigg (2008-11-10 07:37:00)