68

I am using the following to allow my users to select their sex in their profile.

<%= f.select (:sex, %w{ Male Female }) %>

How would I create a blank value that the list would default to if nothing has been passed to the user.sex column? I am simply passing male or female as a string.

The purpose is I want a blank value so a validation can make sure they are aware they have to select it.

bgadoci
  • 6,363
  • 17
  • 64
  • 91

5 Answers5

143

There are two possibilities, depending on what you're after:

include_blank

<%= f.select (:sex, %w{ Male Female }, :include_blank => true) %>

This will always include a blank option in the select, which will allow people to set the value back to the blank value if they're seeing this on an edit form.

prompt

<%= f.select (:sex, %w{ Male Female }, :prompt => "Gender...") %>

This will include the specified prompt value, so long as the field hasn't already been set. If it has (on an edit form for example), there's no need to remind the user that they need to select a value so the prompt doesn't appear

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
Gareth
  • 133,157
  • 36
  • 148
  • 157
  • 5
    The first option will send an empty string with params. Any ideas how to bypass this? – n_x_l Jul 31 '13 at 01:19
  • 1
    @m_w_k: What do you want instead? The whole point of this question was the blank value: "The purpose is I want a blank value so a validation can make sure they are aware they have to select it" – Gareth Jul 31 '13 at 10:16
  • @Gareth yep, sorry. I was caught thinking about my own problem, which is to get rid of the blank submissions (i.e. nullify them). I am now normalising everything in the model. – n_x_l Jul 31 '13 at 17:46
  • 1
    Prompt does not work as stated. Even after another value is selected, the prompt value is still a selectable option. – Eric Chen Feb 18 '17 at 04:19
  • @EricChen That's strange - the behaviour [is documented](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html) as I explained it, and there is [a test that checks this](https://github.com/rails/rails/blob/master/actionview/test/template/form_options_helper_test.rb#L705) in ActionView. Are you sure there's no other issue with your code? – Gareth Feb 20 '17 at 17:59
  • @Gareth thanks for the response, I will check if something else is conflicting and causing it. – Eric Chen Feb 21 '17 at 20:57
40

I think you can do something like this:

<%= f.select (:sex, %w{ Male Female }, {:include_blank => 'None Specified'} ) %>
jyoseph
  • 5,435
  • 9
  • 45
  • 64
  • 3
    This worked in Rails 4. Gareth's answer didn't work for prompting. – Amin Ariana Mar 05 '14 at 20:53
  • Thanks, I struggled to achieve this using simple form. I was using 'prompt: 'none'` for my `new` form but it wasn't showing for my `edit` form. This ensures that `none` is always included as an option. – DazBaldwin Apr 20 '14 at 14:30
4

in Rails 4 you can achieve prompt like this:

<%= f.select :gender, %w{ Male Female }, {:prompt => "Gender..."} %>

its working for me with simple form.

Ziv Galili
  • 1,405
  • 16
  • 20
1

You go with

<%= f.select :gender, %w{ Male Female }, :include_blank => true %>
Hardik Hardiya
  • 837
  • 6
  • 14
0

I tried to use 'prompt' as a string. But in the rendered output, the new option prompt was not appearing. The select_tag method searches only for a symbol. It appears to be the case for :include_blank as well. Check out the options.delete:

  def select_tag(name, option_tags = nil, options = {})
    option_tags ||= ""
    html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name

    if options.include?(:include_blank)
      include_blank = options.delete(:include_blank)

      if include_blank == true
        include_blank = ''
      end

      if include_blank
        option_tags = content_tag(:option, include_blank, value: '').safe_concat(option_tags)
      end
    end

    if prompt = options.delete(:prompt)
      option_tags = content_tag(:option, prompt, value: '').safe_concat(option_tags)
    end

    content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
  end

Also note that :include_blank and :prompt will be options of the select or select_tag, not the options_for_select.

Daniel Viglione
  • 8,014
  • 9
  • 67
  • 101