views:

1523

answers:

4

Hello,

I spent the last three days working on the collection _ select form helper for my "listing" - form, where users can select a category.

I would like to have the category currently set in listing.category_id as the preselected value.

My view code looks like this:

<%= l.collection_select(:category_id, @category, :id, :name, options = {},
      html_options = {:size => 10, :selected => @listing.category_id.to_s})%>

I know this is not correct, but even reading looking at the explanation from Shiningthrough (http://shiningthrough.co.uk/blog/show/6) I can not understand how to proceed.

Thank you for your support,

Michael

View: as above
Controller:

def categories #Step 2
@listing = Listing.find(params[:listing_id])
@seller = Seller.find(@listing.seller_id)
@category = Category.find(:all)
@listing.complete = "step1"

respond_to do |format|
  if @listing.update_attributes(params[:listing])
    flash[:notice] = 'Step one succesful. Item saved.'
    format.html #categories.html.erb
end
end
end
+3  A: 

collection_select doesn't support the selected option, in fact, it doesn't need it. It automatically selects the option whose value matches the value of the form builder object.

Let me show you an example. Assuming each post belongs to a category.

@post = Post.new

<% form_for @post do |f| %>
  <!-- no option selected -->
  <%= f.collection_select :category_id, Category.all, :id, :name, :prompt => true  %>
<% end %>

@post = Post.new(:category_id => 5)

<% form_for @post do |f| %>
  <!-- option with id == 5 is selected -->
  <%= f.collection_select :category_id, Category.all, :id, :name, :prompt => true  %>
<% end %>

EDIT:

I'd suggest to use representative variable names. Use @categories instead of @category. :) Also, split the update logic from the read-only view.

def categories #Step 2
  @listing = Listing.find(params[:listing_id])
  @seller = Seller.find(@listing.seller_id)
  @categories = Category.find(:all)
  @listing.complete = "step1"

  respond_to do |format|
    if @listing.update_attributes(params[:listing])
      flash[:notice] = 'Step one succesful. Item saved.'
      format.html #categories.html.erb
    end
  end
end

<% form_for @listing do |f| %>
  <%= f.collection_select :category_id, @categories, :id, :name, :prompt => true %>
<% end %>

If it doesn't work (that is it selects the prompt) it means either you don't have a category_id associated to that record or the Category collection is empty. Be sure to not reset the value of category_id for @listing somewhere before the object is passed to the form.

EDIT 2:

class Category
  def id_as_string
    id.to_s
  end
end

<%= f.collection_select :category_id, Category.all, :id_as_string, :name, :prompt => true  %>
Simone Carletti
Hi weppos,thanks for the quick and good answer. I expected the collection_select to behave like this, unfortunately, it does not behave like this in my case. Whenever I insert @listing.category_id = 2into my controller, I get the preselected field in the way I want. Even though I got @listing = Listing.find... based on the params and the value is indeed set in the DB, this does not work.I am lost, to be honest.
Michael Schmitz
Could you post a full example, including controller action and view?
Simone Carletti
A: 

My category_id is saved as a string in the database, but the comparison is between integer values.

if @listing.category_id != "" 
@listing.category_id = @listing.category_id.to_i
end

This solves it - the correct value is now pre-selected.

Michael Schmitz
Check my EDIT 2.
Simone Carletti
A: 

Hey all this is testing terminal for select,collect & map

a=["a","b","c","d","e"] => ["a", "b", "c", "d", "e"]

irb(main):002:0> a.map{|i| "a"==i} => [true, false, false, false, false]

irb(main):003:0> a.select{|i|"a"==i} => ["a"]

irb(main):004:0> a.collect{|i|"a"==i} => [true, false, false, false, false]

irb(main):005:0> b=a.map{|i| "a"==i} => [true, false, false, false, false]

irb(main):006:0> print b truefalsefalsefalsefalse=> nil

irb(main):007:0> b=a.select{|i|"a"==i} => ["a"]

irb(main):008:0> print b a=> nil

irb(main):009:0> b=a.collect{|i|"a"==i} => [true, false, false, false, false]

irb(main):010:0> print b truefalsefalsefalsefalse=> nil

irb(main):011:0> b=a.select{|i|"a"+i} => ["a", "b", "c", "d", "e"]

irb(main):012:0> b=a.collect{|i|"a"+i} => ["aa", "ab", "ac", "ad", "ae"]

irb(main):013:0> b=a.map{|i| "a"+i} => ["aa", "ab", "ac", "ad", "ae"]

A: 

Great article, exactly what I was looking for, thanks.

Liron