Rails plugin for enumerations in ActiveRecord models.
Inside your Gemfile
add the following:
gem 'enumerations'
Create a model for your enumerations:
class Status < Enumerations::Base
values draft: { id: 1, name: 'Draft' },
review_pending: { id: 2, name: 'Review pending' },
published: { id: 3, name: 'Published' }
end
Or you can use value
method for defining your enumerations:
class Status < Enumerations::Base
value :draft, id: 1, name: 'Draft'
value :review_pending, id: 2, name: 'Review pending'
value :published, id: 3, name: 'Published'
end
Include enumerations for integer fields in other models:
class Post < ActiveRecord::Base
enumeration :status
validates :status, presence: true # You can validate either :status or :status_id
end
You can pass attributes to specify which enumeration and which column to use:
class Post < ActiveRecord::Base
enumeration :status,
foreign_key: :post_status_id, # specifies which column to use
class_name: Post::Status # specifies the class of the enumerator
validates :post_status, presence: true
end
Attribute foreign_key
you can pass as a String
or a Symbol
. Attribute class_name
can be set as a String
, a Symbol
or a String
.
Set enumerations, find enumerations by symbol
:
@post = Post.first
@post.status = Status.find(:draft)
@post.save
Or you can set enumerations on this way:
@post.status = Status.draft
Also, you can set enumeration value like this:
@post.status_draft!
When you include enumerations into your model, you'll get methods for setting each enumeration value. Each method name is consists from enumeration name and enumeration value name with ! at the end. Examples:
class Post < ActiveRecord::Base
enumeration :status
end
@post.status_draft!
class User < ActiveRecord::Base
enumeration :role
end
@user.role_admin!
class User < ActiveRecord::Base
enumeration :type, class_name: Role
end
@user.type_editor!
Find enumerations by id
:
@post.status = Status.find(2) # => Review pending
@post.save
Other finding methods:
# Find by id as a String
Status.find('2') # => Review pending
# Find by symbol as a String
Status.find('draft') # => Draft
# Find by multiple attributes
Status.find_by(name: 'None', visible: true) # => None
Compare enumerations:
@post.status == :published # => true
@post.status == 3 # => true
@post.status == Status.find(:published) # => true
@post.status.published? # => true
Get all enumerations:
Status.all
Enumerations can be filtered with where
method, similar to ActiveRecord::QueryMethods#where
.
Role.where(admin: true) # => [Role.admin, Role.editor]
Role.where(admin: true, active: true) # => [Role.admin]
With enumerations, you'll get scope for each enumeration value in the following format:
with_#{enumeration_name}_#{enumeration_value_name}
Examples:
class Post < ActiveRecord::Base
enumeration :status
end
Post.with_status_draft # => <#ActiveRecord::Relation []>
Post.with_status_review_pending # => <#ActiveRecord::Relation []>
class Post < ActiveRecord::Base
enumeration :my_status, class_name: Status
end
Post.with_my_status_draft # => <#ActiveRecord::Relation []>
Post.with_my_status_review_pending # => <#ActiveRecord::Relation []>
Each scope returns all records with specified enumeration value.
Use in forms:
%p
= f.label :status_id
%br
= f.collection_select :status_id, Status.all, :id, :name
Except id
and name
you can specify other attributes to your enumerations:
class Status < Enumerations::Base
value :draft, id: 1, name: 'Draft'
value :review_pending, id: 2, name: 'Review pending', description: 'Some description...'
value :published, id: 3, name: 'Published'
end
Every enumeration has id
, name
and description
methods. If you call method that is not in attribute list for enumeration, it will return nil
.
Status.review_pending.description # => 'Some description...'
Status.draft.description # => nil
Enumerations uses power of I18n API to enable you to create a locale file for enumerations like this:
---
en:
enumerations:
status:
draft:
name: Draft
description: Article draft...
...
role:
admin:
name: Administrator
You can separate enumerations locales into a separate
*.yml
files. Then you should add locale file paths to I18n load path:
# config/initializers/locale.rb
# Where the I18n library should search for translation files (e.g.):
I18n.load_path += Dir[Rails.root.join('config', 'locales', 'enumerations', '*.yml')]
Copyright © 2010 Tomislav Car, Infinum Ltd.