How to fix missing Rails select_tag include_blank attribute

If you have ever used the select_tag in Rails, you migth have encountered a situation where you needed an blank option as the first option in your select list, only to discover that it was not supported. How ever, usign the options_for_select you can fix this even when what you really wanted to use, was the options_from_collection_for_select… you have to love those method names :)Fixing this isn’t hard, all that is required is the knowledge of ruby’s array methods and how to change an active record collection into an array.

Here is the finished solution, nice and simple:

<%= select_tag 'project[category_ids][]',
options_for_select(Category.all.collect
{ |c| [c.name, c.id] }.insert(0, '')) %>

- and in the true spirit of the Rails API I have even used a project management app as reference :) As you can see, this is a simple has_and_belongs_to_many association, but you can use this any way you want.

Lets go through the code
By firing up our script/console we can test the code above to get a clearer understanding of what it does. In my case, a Category.all will return something like this:

>> Category.all
=> [#<Category id: 2, name: "Requirement Gathering",
created_at: "2009-06-02 18:49:56", updated_at: "2009-06-02 18:49:56">,
#<Category id: 3, name: "Development Life cycle",
created_at: "2009-06-02 18:57:43", updated_at: "2009-06-02 18:57:43">,
#<Category id: 4, name: "Customer Review & Feedback",
created_at: "2009-06-02 18:59:22", updated_at: "2009-06-02 18:59:22">]

and as you can see using the options_from_collection_for_select I could have written the following:

Category.all, :id, :name

But I need an empty option as the first option in my select list, so using the code above will not work, but by using the option_for_select, which takes an array I can insert an element into the array given it’s index like this:

['Rails', 'PHP', 'JavaScript'].insert(0, "")

Let’s try this in the console and we will get ["", "Rails", "PHP", "JavaScript"] have an empty element with index 0, and the collect method Invokes block once for each element of self. Creates a new array containing the values returned by the block so by using Category.all.collect { |c| [c.id, c.name] } we will get an array build the way the options_for_select likes it, and since the return from that block is an array, we can call the insert method on it and adding the empty options as the first element. We can verify this with the following snippet in our console:

>> Category.all.collect { |c| [c.id, c.name] }.class
=> Array

And by calling the insert method on that snippet we will get:

>> Category.all.collect { |c| [c.id, c.name] }.insert(0,"")
=> ["", [2, "Cat#2"], [3, "Cat#3"], [4, "Cat#4"]]
>>

which will give us what we want; an empty element as the first option in our select_tag.

Enjoy!

About these ads

11 responses to “How to fix missing Rails select_tag include_blank attribute

  1. Thomas

    Exactly what I was looking for, thanks Kristian !

  2. Much obliged, a very nice solution, now retrofitting to some custom helpers.

  3. Just ran into this as well. Above worked like a charm, thanks for posting.

  4. Fred

    options_from_collection_for_select returns a string of option tags, so just specify a blank option tag like this…

    “–not specified–” + options_from_collection_for_select(@duhs, :id, :name, @duh))

  5. Fred

    oops, it chewed up my option tags — well you get the idea.

  6. Thanks so much for taking the time to write this up! I have just used it successfully :)

  7. Gagan

    An alternative can be to add {:include_blank => true} to dispay blank option, which is given by Rails select FormHelper or {:include_blank => “– Select One –”} to display “– Select One –” instead of blank option.

  8. Petros

    Thanks a lot! Very useful!

    Note: it can also be used for the missing :prompt option in the select_tag.

  9. Pingback: Rails options_for_select with include blank and selected option « Kristian Nissen

  10. w@llstreet

    Thank u

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: