GitPedia

Enumerize

Enumerated attributes with I18n and ActiveRecord/Mongoid support

From brainspec·Updated June 10, 2026·View on GitHub·

Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support The project is written primarily in Ruby, distributed under the MIT License license, first published in 2012. It has gained significant community traction with 1,764 stars and 200 forks on GitHub. Key topics include: activerecord, mongoid, ruby.

Latest release: v2.5.0
December 24, 2021View Changelog →

Enumerize Ruby

Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support

Table of Contents

Installation

Add this line to your application's Gemfile:

gem 'enumerize'

And then execute:

$ bundle

Or install it yourself as:

$ gem install enumerize

Supported Versions

  • Ruby 3.1+
  • Rails 7.0+

Usage

Basic:

ruby
class User extend Enumerize enumerize :role, in: [:user, :admin] end

Note that enumerized values are just identifiers so if you want to use multi-word, etc. values then you should use I18n feature.


Database support

ActiveRecord

ruby
class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :status t.string :role t.timestamps end end end class User < ActiveRecord::Base extend Enumerize enumerize :status, in: [:student, :employed, :retired], default: lambda { |user| StatusIdentifier.status_for_age(user.age).to_sym } enumerize :role, in: [:user, :admin], default: :user end

:warning: By default, enumerize adds inclusion validation to the model. You can skip validations by passing skip_validations option. :warning:

ruby
class User < ActiveRecord::Base extend Enumerize enumerize :status, in: [:student, :employed, :retired], skip_validations: lambda { |user| user.new_record? } enumerize :role, in: [:user, :admin], skip_validations: true end

Mongoid

ruby
class User include Mongoid::Document extend Enumerize field :role enumerize :role, in: [:user, :admin], default: :user end

MongoMapper

ruby
class User include MongoMapper::Document extend Enumerize key :role enumerize :role, in: [:user, :admin], default: :user end

I18n Support

ruby
en: enumerize: user: status: student: "Student" employed: "Employed" retired: "Retiree"

or if you use status attribute across several models you can use defaults scope:

ruby
en: enumerize: defaults: status: student: "Student" employed: "Employed" retired: "Retiree"

You can also pass i18n_scope option to specify scope (or array of scopes) storing the translations.

ruby
class Person extend Enumerize extend ActiveModel::Naming enumerize :status, in: %w[student employed retired], i18n_scope: "status" enumerize :roles, in: %w[user admin], i18n_scope: ["user.roles", "roles"] enumerize :color, in: %w[green blue], i18n_scope: proc { |value| "color" } end # localization file en: status: student: "Student" employed: "Employed" retired: "Retiree" user: roles: user: "User" roles: admin: "Admin"

Note that if you want to use I18n feature with plain Ruby object don't forget to extend it with ActiveModel::Naming:

ruby
class User extend Enumerize extend ActiveModel::Naming end

I18n Helper Methods

*_text / .text

Attribute's I18n text value:

ruby
@user.status_text # or @user.status.text

values

List of possible values for an enumerized attribute:

ruby
User.status.values # or User.enumerized_attributes[:status].values # => ['student', 'employed', 'retired']

I18n text values

List of possible I18n text values for an enumerized attribute:

ruby
User.status.values.collect(&:text) # => ['Student', 'Employed', 'Retiree']

Form example

Use it with forms (it supports :only and :except options):

erb
<%= form_for @user do |f| %> <%= f.select :status, User.status.options %> <% end %>

Boolean Helper Methods

Basic

ruby
user.status = :student user.status.student? #=> true user.status.retired? #=> false

Predicate Methods

ruby
class User extend Enumerize enumerize :status, in: %w(student employed retired), predicates: true end user = User.new user.student? # => false user.employed? # => false user.status = :student user.student? # => true user.employed? # => false

:warning: If enumerize is used with Mongoid, it's not recommended to use "writer" as a field value since writer? is defined by Mongoid. See more. :warning:

Predicate Prefixes

ruby
class User extend Enumerize enumerize :status, in: %w(student employed retired), predicates: { prefix: true } end user = User.new user.status = 'student' user.status_student? # => true

Use :only and :except options to specify what values create predicate methods for.


Optimzations and Tips

Extendable Module

To make some attributes shared across different classes it's possible to define them in a separate module and then include it into classes:

ruby
module RoleEnumerations extend Enumerize enumerize :roles, in: %w[user admin] end class Buyer include RoleEnumerations end class Seller include RoleEnumerations end

Customizing Enumerize Value

It's also possible to store enumerized attribute value using custom values (e.g. integers). You can pass a hash as :in option to achieve this:

ruby
class User < ActiveRecord::Base extend Enumerize enumerize :role, in: { user: 1, admin: 2 } end user = User.new user.role = :user user.role #=> 'user' user.role_value #=> 1 User.role.find_value(:user).value #=> 1 User.role.find_value(:admin).value #=> 2

ActiveRecord scopes:

Basic

ruby
class User < ActiveRecord::Base extend Enumerize enumerize :role, in: [:user, :admin], scope: true enumerize :status, in: { student: 1, employed: 2, retired: 3 }, scope: :having_status end User.with_role(:admin) # SELECT "users".* FROM "users" WHERE "users"."role" IN ('admin') User.without_role(:admin) # SELECT "users".* FROM "users" WHERE "users"."role" NOT IN ('admin') User.having_status(:employed).with_role(:user, :admin) # SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."role" IN ('user', 'admin')

Shallow Scopes

Adds named scopes to the class directly.

ruby
class User < ActiveRecord::Base extend Enumerize enumerize :status, in: [:student, :employed, :retired], scope: :shallow enumerize :role, in: { user: 1, admin: 2 }, scope: :shallow end User.student # SELECT "users".* FROM "users" WHERE "users"."status" = 'student' User.admin # SELECT "users".* FROM "users" WHERE "users"."role" = 2

:warning: It is not possible to define a scope when using the :multiple option. :warning:

Array-like Attributes

Array-like attributes with plain ruby objects:

ruby
class User extend Enumerize enumerize :interests, in: [:music, :sports], multiple: true end user = User.new user.interests << :music user.interests << :sports

and with ActiveRecord:

ruby
class User < ActiveRecord::Base extend Enumerize serialize :interests, Array enumerize :interests, in: [:music, :sports], multiple: true end

get an array of all text values:

ruby
@user.interests.texts # shortcut for @user.interests.map(&:text)

Also, the reader method can be overridden, referencing the enumerized attribute value using super:

ruby
def status if current_user.admin? "Super #{super}" else super end end

Forms

SimpleForm

If you are using SimpleForm gem you don't need to specify input type (:select by default) and collection:

erb
<%= simple_form_for @user do |f| %> <%= f.input :status %> <% end %>

and if you want it as radio buttons:

erb
<%= simple_form_for @user do |f| %> <%= f.input :status, as: :radio_buttons %> <% end %>

Please note that Enumerize overwrites the I18n keys of SimpleForm collections. The enumerized keys are used instead of the SimpleForm ones for inputs concerning enumerized attributes. If you don't want this just pass :collection option to the input call.

Formtastic

If you are using Formtastic gem you also don't need to specify input type (:select by default) and collection:

erb
<%= semantic_form_for @user do |f| %> <%= f.input :status %> <% end %>

and if you want it as radio buttons:

erb
<%= semantic_form_for @user do |f| %> <%= f.input :status, as: :radio %> <% end %>

Testing

RSpec

Also you can use builtin RSpec matcher:

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired] end describe User do it { should enumerize(:status) } # or with RSpec 3 expect syntax it { is_expected.to enumerize(:status) } end

Qualifiers

in

Use in to test usage of the :in option.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired] end describe User do it { should enumerize(:status).in(:student, :employed, :retired) } end

You can test enumerized attribute value using custom values with the in
qualifier.

ruby
class User extend Enumerize enumerize :role, in: { user: 0, admin: 1 } end describe User do it { should enumerize(:role).in(user: 0, admin: 1) } end
with_default

Use with_default to test usage of the :default option.

ruby
class User extend Enumerize enumerize :role, in: [:user, :admin], default: :user end describe User do it { should enumerize(:user).in(:user, :admin).with_default(:user) } end
with_i18n_scope

Use with_i18n_scope to test usage of the :i18n_scope option.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired], i18n_scope: 'status' end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_i18n_scope('status') } end
with_predicates

Use with_predicates to test usage of the :predicates option.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired], predicates: true end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(true) } end

You can text prefixed predicates with the with_predicates qualifiers.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired], predicates: { prefix: true } end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(prefix: true) } end
with_scope

Use with_scope to test usage of the :scope option.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired], scope: true end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_scope(true) } end

You can test a custom scope with the with_scope qualifiers.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed], scope: :employable end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_scope(scope: :employable) } end
with_multiple

Use with_multiple to test usage of the :multiple option.

ruby
class User extend Enumerize enumerize :status, in: [:student, :employed, :retired], multiple: true end describe User do it { should enumerize(:status).in(:student, :employed, :retired).with_multiple(true) } end

Minitest with Shoulda

You can use the RSpec matcher with shoulda in your tests by adding two lines in your test_helper.rb inside class ActiveSupport::TestCase definition:

ruby
class ActiveSupport::TestCase ActiveRecord::Migration.check_pending! require 'enumerize/integrations/rspec' extend Enumerize::Integrations::RSpec ... end

Other Integrations

Enumerize integrates with the following automatically:


Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Contributors

Showing top 12 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from brainspec/enumerize via the GitHub API.Last fetched: 6/14/2026