Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Enumerated Types or Alternatives

I'm just learning ruby on rails and I have a table of user roles (Owner, Admin, and User). There are going to be places in the code where I need to check the user's role and show different options. Does anyone know how to do this without resorting to magic numbers or other ugly methods?

In ASP.Net web apps I've worked on I've seen this done through the use of enumerated types:

public enum UserRole { Owner = 1, Admin = 2, User = 3 }

// ...

if (user.Role == UserRole.Admin)
    // Show special admin options

Each different role in the database is reflected as an enumerated type with a value set to the ID of that role in the database. That doesn't seem like a very good solution because it depends on knowledge of database that may change. Even if it is the proper way to handle something like this, I don't know how to use enumerated types in rails.

I would appreciate any insight into this matter.

like image 493
Jason Avatar asked May 26 '09 04:05

Jason


People also ask

How to use enum in Rails model?

Various ways to define enum in modelWe run the migration using rake db:migrate and in our Post model, we need to define the enum as shown in the below example. The enum method expects the column attribute name which it should refer to and the second parameter is a list of values a post status can have.


3 Answers

Ruby itself does not have an enumerated type, but this site shows a method http://www.rubyfleebie.com/enumerations-and-ruby/

You could make something like this in your User model:

#constants
OWNER = 1
ADMIN = 2
USER = 3

def is_owner?
  self.role == OWNER
end

def is_admin?
  self.role == ADMIN
end

def is_user?
  self.role == USER
end
like image 66
Reuben Mallaby Avatar answered Oct 10 '22 21:10

Reuben Mallaby


Could the functionality added in Rails 4.1, be what you are looking for ?

http://coherence.io/blog/2013/12/17/whats-new-in-rails-4-1.html

Copy from blog post:

class Bug < ActiveRecord::Base
  # Relevant schema change looks like this:
  #
  # create_table :bugs do |t|
  #   t.column :status, :integer, default: 0 # defaults to the first value (i.e. :unverified)
  # end

  enum status: [ :unverified, :confirmed, :assigned, :in_progress, :resolved, :rejected, :reopened ]

...

Bug.resolved           # => a scope to find all resolved bugs
bug.resolved?          # => check if bug has the status resolved
bug.resolved!          # => update! the bug with status set to resolved
bug.status             # => a string describing the bug's status
bug.status = :resolved # => set the bug's status to resolved
like image 13
Dimitrios Mistriotis Avatar answered Oct 10 '22 21:10

Dimitrios Mistriotis


This seems like a really good case for using my classy_enum gem. It essentially allows you to define a fixed set of options, where each one is a class with behavior and properties specific to it. It helps cut down on all the conditional logic that tends to get scattered throughout the application.

For example, If you are doing things like this:

class User < ActiveRecord::Base
  def options
    if user.is_admin?
      [...admin options...]
    else
      [...non admin options...]
    end
  end
end

Then calling as: user.options somewhere else...

classy_enum allows you to move that logic to a separate place and have the same functionality with no conditional logic:

class User < ActiveRecord::Base
  classy_enum_attr :role

  delegate :options, :to => :role
end

The README has a working example and describes the gem in detail.

like image 4
Peter Brown Avatar answered Oct 10 '22 19:10

Peter Brown