views:

1138

answers:

3

Is it possible to add an <option> at the end of a <select> created with the collection_select helper method?

Right now I have

f.collection_select(:category_id , @categories, :id, :name, {:prompt => 'Please select a category'})

which generates

<select id="product_category_id" name="product[category_id]">
  <option value="">Please select a category</option>
  <option value="7">category one</option>
  <option value="8">category 2</option>
</select>

and what I would like is

<select id="product_category_id" name="product[category_id]">
  <option value="">Please select a category</option>
  <option value="7">category one</option>
  <option value="8">category 2</option>
  <option value="new">..or create a new one</option>
</select>

Is this possible or should I just loop through the collection and generate the options manually?

A: 

Short answer: no.

Long answer: Sure, but you have to be crafty.

  • Create a class like so:

    class New_option_placeholder
        def id 
            "new"
            end
        def name
            "...or create a new one"
            end
        end
    
  • Instead of passing @categories, pass @categories+New_option_placeholder.new

If (as indicated by the comments) you're looking for something terser you could require "ostruct" and then pass @categories + [OpenStruct.new(:id => 'new',:name => '...or create a new one')] to accomplish essentially the same this.

MarkusQ
This would probably work, but it's too much of a workaround so I think I'll go for Gdeglin's solution. +1 still 'cause it does what I wanted
andi
I think by the time you get Gdeglin's solution working you'll have something with more moving parts than this. If you're just looking for a one-line version I'll add one...
MarkusQ
+4  A: 

You should probably use select instead.

Like so:

f.select(:category_id, @categories.collect {|p| [ p.name, p.id ] } + ['Or create a new one','new'], {:include_blank => 'Please select a category'})

Good luck!

Gdeglin
umm.. this creates 2 extra options, both with name equal with value, "Or create a new one" and "new"
andi
I also tried with a hash instead of an array, Hash["name", "create a new one", "id", "new"], but I get a "can't convert Hash into Array".. figures..
andi
so.. this would do, but, any ideas on how to set a value different than the text inside the option?
andi
A: 

Agreed on the short answer No and long answer " Be Crafty ", but here's what I just did which I think is simpler than either of these two solutions and worked for me:

Wrap the next line inside erb tags i.e. <%= and %>:

f.collection_select :advertisement_group_id, AdvertisementGroup.find(:all, :order => "name DESC") << AdvertisementGroup.new(:name => "New Group"), :id, :name, :include_blank => true  

Just create a new object with .new and pass in whatever text you want displayed along with :include_blank => true.

fuzzygroup