Project

nd-enum

0.0
No release in over a year
Powerful enum for Rails models.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

 Project Readme

ND::Enum

This gem allows you to create and use enums easily and quickly in your Rails project.

Installation

Install the gem and add to the application's Gemfile by executing:

$ bundle add nd-enum

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install nd-enum

Usage

  • Basic usage
  • Configuration
  • I18n
    • Validate translations presence
    • Enforce translations presence
  • ActiveRecord Enum

Basic usage

Define your enum in an ActiveRecord model:

class User < ApplicationRecord
  nd_enum(role: %i(user admin))
end

It creates a module for your enum that contains one constant per enum value. Say goodbye to magic strings!

In our example, the module is User::Role, and the constants are User::Role::USER and User::Role::ADMIN.

irb(main)> User::Role::USER
=> "user"

irb(main)> User::Role::ADMIN
=> "admin"

irb(main)> User::Role.all
=> ["user", "admin"]

irb(main)> User::Role.length
=> 2

irb(main)> User::Role[1]
=> "admin"

irb(main)> User::Role[:user]
=> "user"

irb(main)> User::Role.include?('foobar')
=> false

irb(main)> User::Role.include?('user')
=> true

ND::Enum inheritates from Enumerable, so it is possible to use all Enumerable methods on the enum module: each, map, find...

Configuration

Fine-tune ND::Enum behaviour by creating an initializer (for example: config/initializers/nd_enum.rb). The values shown in the example below are the default values.

ND::Enum.configure do |c|
  c.default_i18n_scope = :base
  c.default_i18n_validation_mode = :ignore # Allowed values: ignore, log, enforce
end

I18n

Allows to translate your enum values. Add to your locale files:

en:
  users: # Model.table_name
    role: # attribute
      base: # default scope
        user: User
        admin: Admin
      foobar: # custom scope
        user: The user
        admin: The admin

Then call t (or translate) method:

irb(main)> User::Role.t(:user) # Or `translate` method (alias)
=> "translation missing: en.users.role.base.user"

Use a different scope to have several translations for a single value, depending on context:

irb(main)> User::Role.t(:user, :foobar)
=> "translation missing: en.users.role.foobar.user"

Please note that the default scope (base) can be configured using the default_i18n_scope initializer option.

Validate translations presence

Validate that your enum are translated. By default, this feature is disabled.

class User < ApplicationRecord
  nd_enum(role: %i(user admin), i18n: { mode: :log })
end

It will log the missing translations for each scope & locale. For example:

I, [2022-08-10T21:17:53.931669 #67401]  INFO -- : ND::Enum: User#role scopes=[:base, :short]
I, [2022-08-10T21:17:53.931669 #67401]  INFO -- : ND::Enum: User#role locale=en missing_keys=[]
I, [2022-08-10T21:17:53.931669 #67401]  INFO -- : ND::Enum: User#role locale=nl missing_keys=["users.role.base.user", "users.role.short.user"]

This mode can be used as default with the c.default_i18n_validation_mode = :log initializer option.

Enforce translations presence

Raise an exception when some translations are missing.

class User < ApplicationRecord
  nd_enum(role: %i(user admin), i18n: { mode: :enforce })
end
(irb):1:in `<main>': One or several translations are missing (ND::Enum::MissingTranslationError)
        from bin/console:15:in `<main>'

This mode can be used as default with the c.default_i18n_validation_mode = :enforce initializer option.

ActiveRecord Enum

Add a wrapper to ActiveRecord Enum by specifying the db: true option.

class User < ApplicationRecord
  nd_enum(role: %i(user admin), db: true)
end

# It does exactly the same thing than below, but shorter:

class User < ApplicationRecord
  nd_enum(role: %i(user admin))
  enum(role: User::Role.to_h) # Or `enum(role: { user: 'user', admin: 'admin '})`
end

It allows to use these methods:

user.admin!
user.admin? # => true
user.role # => "admin"

And these scopes:

User.admin
User.not_admin

User.user
User.not_user

# ...

Disable scope definition by setting scopes: false to your enum:

class User < ApplicationRecord
  nd_enum(role: %i(user admin), db: { scopes: false })
end

Set the default enum:

class User < ApplicationRecord
  nd_enum(role: %i(user admin), db: { default: :admin })
end

Add a prefix or suffix option when you need to define multiple enums with same values. If the passed value is true, the methods are prefixed/suffixed with the name of the enum. It is also possible to supply a custom value:

class User < ApplicationRecord
  nd_enum(role: %i(user admin), db: { prefix: true })

  # Scopes: `User.role_admin`, `User.role_user` ...
  # Methods: `User.role_admin!`, `User.role_user!` ...

  nd_enum(role: %i(user admin), db: { suffix: true })

  # Scopes: `User.admin_role`, `User.user_role` ...
  # Methods: `User.admin_role!`, `User.user_role!` ...

  nd_enum(role: %i(user admin), db: { prefix: 'foobar' })

  # Scopes: `User.foobar_admin`, `User.foobar_user` ...
  # Methods: `User.foobar_admin!`, `User.foobar_user!` ...
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Guard is also installed: bundle exec guard.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, run gem bump (or manually update the version number in version.rb), and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/rclavel/nd-enum.

License

The gem is available as open source under the terms of the MIT License.