Need help with enumerize?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

brainspec
1.6K Stars 165 Forks MIT License 609 Commits 7 Opened issues

Description

Enumerated attributes with I18n and ActiveRecord/Mongoid support

Services available

!
?

Need anything else?

Contributors list

Enumerize TravisCI

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

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 2.5+
  • Rails 5.2+

Usage

Basic:

class User
  extend Enumerize

enumerize :sex, in: [:male, :female] end

Note that enumerized values are just identificators so if you want to use multi-word, etc. values you should use

I18n
feature.

ActiveRecord:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :sex
      t.string :role

  t.timestamps
end

end end

class User < ActiveRecord::Base extend Enumerize

enumerize :sex, in: [:male, :female], default: lambda { |user| SexIdentifier.sex_for_name(user.name).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:
class User < ActiveRecord::Base
  extend Enumerize

enumerize :sex, in: [:male, :female], skip_validations: lambda { |user| user.new_record? }

enumerize :role, in: [:user, :admin], skip_validations: true end

Mongoid:

class User
  include Mongoid::Document
  extend Enumerize

field :role enumerize :role, in: [:user, :admin], default: :user end

MongoMapper:

class User
  include MongoMapper::Document
  extend Enumerize

key :role enumerize :role, in: [:user, :admin], default: :user end

I18n:

en:
  enumerize:
    user:
      sex:
        male: "Male"
        female: "Female"

or if you use

sex
attribute across several models you can use
defaults
scope:
en:
  enumerize:
    defaults:
      sex:
        male: "Male"
        female: "Female"

You can also pass

i18n_scope
option to specify scope (or array of scopes) storing the translations.
class Person
  extend Enumerize
  extend ActiveModel::Naming

enumerize :sex, in: %w[male female], i18n_scope: "sex" enumerize :color, in: %w[black white], i18n_scope: ["various.colors", "colors"] end

localization file

en: sex: male: "Male" female: "Female" various: colors: black: "Black" colors: white: "White"

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

ActiveModel::Naming
:
class User
  extend Enumerize
  extend ActiveModel::Naming
end

get attribute value:

@user.sex_text # or @user.sex.text

get all values for enumerized attribute:

User.sex.values # or User.enumerized_attributes[:sex].values

use it with forms (it supports

:only
and
:except
options):

Boolean methods:

user.sex = :male
user.sex.male? #=> true
user.sex.female? #=> false

Predicate methods:

class User
  extend Enumerize

enumerize :sex, in: %w(male female), predicates: true end

user = User.new

user.male? # => false user.female? # => false

user.sex = 'male'

user.male? # => true user.female? # => 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:

Using prefix:

class User
  extend Enumerize

enumerize :sex, in: %w(male female), predicates: { prefix: true } end

user = User.new user.sex = 'female' user.sex_female? # => true

Use

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

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

module PersonEnumerations
  extend Enumerize

enumerize :sex, in: %w[male female] end

class Person include PersonEnumerations end

class User include PersonEnumerations end

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:
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:

class User < ActiveRecord::Base
  extend Enumerize
  enumerize :sex, :in => [:male, :female], scope: true
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
end

User.with_sex(:female)

SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')

User.without_sex(:male)

SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')

User.having_status(:blocked).with_sex(:male, :female)

SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')

Shallow scopes:

Adds named scopes to the class directly

class User < ActiveRecord::Base
  extend Enumerize
  enumerize :sex, :in => [:male, :female], scope: :shallow
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: :shallow
end

User.male

SELECT "users".* FROM "users" WHERE "users"."sex" = 'male'

User.active

SELECT "users".* FROM "users" WHERE "users"."status" = 1

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

:multiple
option. :warning:

Array-like attributes with plain ruby objects:

class User
  extend Enumerize

enumerize :interests, in: [:music, :sports], multiple: true end

user = User.new user.interests << :music user.interests << :sports

and with ActiveRecord:

class User < ActiveRecord::Base
  extend Enumerize

serialize :interests, Array enumerize :interests, in: [:music, :sports], multiple: true end

get an array of all text values:

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

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

super
:
def sex
  if current_user.admin?
    "Super#{super}"
  else
    super
  end
end

SimpleForm

If you are using SimpleForm gem you don't need to specify input type (

:select
by default) and collection:

and if you want it as radio buttons:

   :radio_buttons %>

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:

and if you want it as radio buttons:

   :radio %>

RSpec

Also you can use builtin RSpec matcher:

class User
  extend Enumerize

enumerize :sex, in: [:male, :female] end

describe User do it { should enumerize(:sex) }

or with RSpec 3 expect syntax

it { is_expected.to enumerize(:sex) } end

Qualifiers

in

Use

in
to test usage of the
:in
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female] end

describe User do it { should enumerize(:sex).in(:male, :female) } end

You can test enumerized attribute value using custom values with the

in
qualifier.
class User
  extend Enumerize

enumerize :sex, in: { male: 0, female: 1 } end

describe User do it { should enumerize(:sex).in(male: 0, female: 1) } end

with_default

Use

with_default
to test usage of the
:default
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], default: :female end

describe User do it { should enumerize(:sex).in(:male, :female).with_default(:female) } end

withi18nscope

Use

with_i18n_scope
to test usage of the
:i18n_scope
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], i18n_scope: 'sex' end

describe User do it { should enumerize(:sex).in(:male, :female).with_i18n_scope('sex') } end

with_predicates

Use

with_predicates
to test usage of the
:predicates
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], predicates: true end

describe User do it { should enumerize(:sex).in(:male, :female).with_predicates(true) } end

You can text prefixed predicates with the

with_predicates
qualifiers.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], predicates: { prefix: true } end

describe User do it { should enumerize(:sex).in(:male, :female).with_predicates(prefix: true) } end

with_scope

Use

with_scope
to test usage of the
:scope
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], scope: true end

describe User do it { should enumerize(:sex).in(:male, :female).with_scope(true) } end

You can text custom scope with the

with_scope
qualifiers.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], scope: :having_sex end

describe User do it { should enumerize(:sex).in(:male, :female).with_scope(scope: :having_sex) } end

with_multiple

Use

with_multiple
to test usage of the
:multiple
option.
class User
  extend Enumerize

enumerize :sex, in: [:male, :female], multiple: true end

describe User do it { should enumerize(:sex).in(:male, :female).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:
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

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.