12

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?

andi
  • 14,322
  • 9
  • 47
  • 46

4 Answers4

11

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!

jsmorris
  • 319
  • 2
  • 10
Gdeglin
  • 12,432
  • 5
  • 49
  • 65
  • umm.. this creates 2 extra options, both with name equal with value, "Or create a new one" and "new" – andi Mar 31 '09 at 07:59
  • 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 Mar 31 '09 at 08:03
  • so.. this would do, but, any ideas on how to set a value different than the text inside the option? – andi Mar 31 '09 at 08:21
3

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.

sth
  • 222,467
  • 53
  • 283
  • 367
fuzzygroup
  • 1,109
  • 12
  • 12
1

I can't comment otherwise I'd add this to the answer above.

To get the option->value "new","or create a new one".. instead of

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

do

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

note the extra [] around the options. This makes the array work as an option,value pair

patrickdavey
  • 1,966
  • 2
  • 18
  • 25
1

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.

manveru
  • 2,770
  • 1
  • 20
  • 17
MarkusQ
  • 21,814
  • 3
  • 56
  • 68
  • 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 Mar 31 '09 at 08:07
  • 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 Mar 31 '09 at 15:01