whitelka
whitelka

Reputation: 31

How to use enum(rails 4.1)?

I'm trying to use enum in my project. but I don't know how to use it with simple_form input collection. my code makes an error. this is my enum definition in user.rb:

    enum role: [ :guest, :super_admin, :advertiser, :publisher, :account_manager]

and this is my view code:

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
    <%= render 'devise/shared/error_messages', object: f.object %>
    <div class="form-inputs">
       <%= f.input :name, required: true, autofocus: true%>
       <%= f.input :email, required: true %>
      <%= f.input :password, required: true, placeholder: "min. 6 characters",
                  input_html: {"parsley-minlength" => 6, "error-container" =>"#errorBlock"} %>
      <%= f.input :password_confirmation, required: true,
                  input_html: {"parsley-equalto" => "#user_password"} %>
      **<%= f.input :role, collection: User.roles %>**

    </div>

Upvotes: 3

Views: 6371

Answers (3)

LesterZhao
LesterZhao

Reputation: 1

Add this line to your application's Gemfile:

gem 'enum_help'

And then execute:

$ bundle

In model

 enum role: [ :guest, :super_admin, :advertiser, :publisher, :account_manager]

In _form.html.erb using simple_form:

<%= f.input :role %>

For more information: https://github.com/zmbacker/enum_help

Upvotes: -1

kobaltz
kobaltz

Reputation: 7070

When you do something like Resource.roles it will return a hash of keys and values like

{"guest"=>0, "super_admin"=>1, ...}

However, if you're using the enum in a form, by default it will simple display an integer field. Using simple_form, you can specify a collection set for the enum and it will return an array of the keys.

<%= f.input :role, collection: User.roles.keys %>

Since you pass in the collection: option, it will automatically change the input field to a select. However, you can specify this manually as well with as: :select or use check boxes.

Note that User.roles.keys will return

["guest", "super_admin", ... ]

This should fix the error message that you were receiving. Before, it was displaying the enum name and the selection was setting the integer value of the enum. When setting a value for an enum attribute, you actually specify the key name, not the integer value.

This is from the documentation http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html#method-i-inherited

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.update! status: 1
conversation.status = "archived"

# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

Note where they set the value of the status conversation.status = "archived", they set the key name of the enum and not the value 1. Hopefully this helps you.

Upvotes: 8

tejasbubane
tejasbubane

Reputation: 942

As I can see, User.roles will not return an array but will return a Hash like

{"guest"=>0, "super_admin"=>1, ...}

Also I don't know your migrations, but make sure you have the role field as integer in the database and not a string.

For more details on Rails enums refer the official manual and this awesome article on enums by thoughtbot

Upvotes: 0

Related Questions