Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving enum from select in Rails 4.1

Alright, so apparently, you shouldn't send the integer value of the enum to be saved. You should send the text value of the enum.

I changed the input to be the following:

f.input :color, :as => :select, :collection => Wine.colors.keys.to_a

Which generated the following HTML:

<select id="wine_color" name="wine[color]">
  <option value=""></option>
  <option value="red">red</option>
  <option value="white">white</option>
  <option value="sparkling">sparkling</option>
</select>

Values went from "0" to "red" and now we're all set.


If you're using a regular ol' rails text_field it's:

f.select :color, Wine.colors.keys.to_a

If you want to have clean human-readable attributes you can also do:

f.select :color, Wine.colors.keys.map { |w| [w.humanize, w] }

No need converting the enum hash to array with to_a. This suffice:

f.select :color, Wine.colors.map { |key, value| [key.humanize, key] }

The accepted solution didn't work for me for the human readable, but I was able to get it to work like this:

<%= f.select(:color, Wine.colors.keys.map {|key| [key.humanize, key]}) %>

This was the cleanest, but I really needed to humanize my keys:

<%= f.select(:color, Wine.colors.keys) %>

I just put together an EnumHelper that I thought I'd share to help people who need more customised enum labels and locales for your enum selects.

module EnumHelper

  def options_for_enum(object, enum)
    options = enums_to_translated_options_array(object.class.name, enum.to_s)
    options_for_select(options, object.send(enum))
  end

  def enums_to_translated_options_array(klass, enum)
    klass.classify.safe_constantize.send(enum.pluralize).map {
        |key, value| [I18n.t("activerecord.enums.#{klass.underscore}.#{enum}.#{key}"), key]
    }
  end

end

In your locale:

 en:
   activerecord:
     enums:
      wine:
        color:
          red:   "Red Wine"
          white:  "White Wine"

In your views:

 <%= f.select(:color, options_for_enum(@wine, :color)) %>

If you use enum in Rails 4 then just call Model.enums:

f.select :color, Wine.colors.keys

To create HTML:

<select name="f[color]" id="f_color">
    <option value="red">red</option>
    <option value="white">white</option>
    <option value="sparkling"> sparkling </option>
</select>

Or add method in controller:

def update_or_create
    change_enum_to_i
    ....
end

def change_enum_to_i
    params[:f]["color"] = params[:f]["color"].to_i
end