Enums In Rails 4.1 Forms
I've been working on upgrading Passkeep this weekend which includes a complete overhaul of the UI, a re-write of all the code, and an upgrade to the latest version of Rails. One of the new features of RoR 4.1 is enums which I've used for a long time in other languages like C#, but haven't been supported in Rails before.
Our project model has a status enum to allow users to hide older projects from the project list view. To update our old hash to the latest rails, we simply add this enum to the Project model with an existing status integer.
class Project < ActiveRecord::Base
enum status: {
active: 1,
archived: 2
}
end
Now we get a lot of helpers for our project model.
# conversation.update! status: 0
project.active!
project.active? # => true
project.status # => "active"
# project.update! status: 1
project.archived!
project.archived? # => true
project.status # => "archived"
# project.update! status: 1
project.status = "archived"
# project.update! status: nil
project.status = nil
project.status.nil? # => true
project.status # => nil
Great!
The only problem I ran into was using enums in my project form. I figured it would work by just passing in the enum to my collection like this
simple_form and slim
= f.input :status, collection: Project.statuses
erb and default form helpers
<%= f.select :status, options_for_select(Project.statuses) %>
This however produces an error when submitting the form
'1' is not a valid status_id
Not great.
It turns out that Rails expects the status property to either be an exact match of the enum string key, but so I had to update my form to use the key as the value.
simple_form and slim
= f.input :status, collection: Project.status.map {|k, v| [k, k]}
erb and default form helpers
<%= f.select :status, options_for_select(Project.status.map {|k, v| [k, k]}) %>
Problem solved, but this seems like a pretty odd requirement for Rails.
Update: 2015.02.20
As @Mattia points out below, if you have simple keys, you can also use
<%= f.select :status, options_for_select(Project.statuses.keys) %>
In practice though, I've found I more often than not keep my enum keys as standard symbols and use this to make them legible.
<%= f.select :status, options_for_select(Project.statuses.map {|k, v| [k.humanize.capitalize, k]}) %>