{"id":13427699,"url":"https://github.com/brainspec/enumerize","last_synced_at":"2025-05-11T05:36:07.228Z","repository":{"id":2304972,"uuid":"3264002","full_name":"brainspec/enumerize","owner":"brainspec","description":"Enumerated attributes with I18n and ActiveRecord/Mongoid support","archived":false,"fork":false,"pushed_at":"2025-02-22T21:24:38.000Z","size":675,"stargazers_count":1752,"open_issues_count":5,"forks_count":194,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-05-08T00:55:23.045Z","etag":null,"topics":["activerecord","mongoid","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brainspec.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-01-25T10:31:04.000Z","updated_at":"2025-05-07T12:16:07.000Z","dependencies_parsed_at":"2024-01-23T19:25:00.146Z","dependency_job_id":"e8be0192-b697-4cc7-8f31-0ae2aeb37c11","html_url":"https://github.com/brainspec/enumerize","commit_stats":{"total_commits":519,"total_committers":80,"mean_commits":6.4875,"dds":0.6223506743737958,"last_synced_commit":"2dcc74e3e0ac60729216998d45c207ec3aa59e14"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brainspec%2Fenumerize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brainspec%2Fenumerize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brainspec%2Fenumerize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brainspec%2Fenumerize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brainspec","download_url":"https://codeload.github.com/brainspec/enumerize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252978740,"owners_count":21834915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","mongoid","ruby"],"created_at":"2024-07-31T01:00:38.455Z","updated_at":"2025-05-08T00:55:28.279Z","avatar_url":"https://github.com/brainspec.png","language":"Ruby","readme":"# Enumerize [![Ruby](https://github.com/brainspec/enumerize/actions/workflows/ruby.yml/badge.svg)](https://github.com/brainspec/enumerize/actions/workflows/ruby.yml)\n\nEnumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper/Sequel support\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Supported Versions](#supported-versions)\n- [Usage](#usage)\n- [Database support](#database-support)\n  - [ActiveRecord](#activerecord)\n  - [Mongoid](#mongoid)\n  - [MongoMapper](#mongomapper)\n- [I18n Support](#i18n-support)\n  - [I18n Helper Methods](#i18n-helper-methods)\n- [Boolean Helper Methods](#boolean-helper-methods)\n  - [Basic](#basic)\n  - [Predicate Methods](#predicate-methods)\n- [Optimzations and Tips](#optimzations-and-tips)\n  - [Extendable Module](#extendable-module)\n  - [Customizing Enumerize Value](#customizing-enumerize-value)\n  - [ActiveRecord scopes](#activerecord-scopes)\n  - [Array-like Attributes](#array-like-attributes)\n- [Forms](#forms)\n  - [SimpleForm](#simpleform)\n  - [Formtastic](#formtastic)\n- [Testing](#testing)\n  - [RSpec](#rspec)\n  - [Minitest with Shoulda](#minitest-with-shoulda)\n  - [Other Integrations](#other-integrations)\n- [Contributing](#contributing)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'enumerize'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install enumerize\n\n## Supported Versions\n\n- Ruby 3.1+\n- Rails 7.0+\n\n## Usage\n\nBasic:\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :role, in: [:user, :admin]\nend\n```\n\nNote that enumerized values are just identifiers so if you want to use multi-word, etc. values then you should use `I18n` feature.\n\n---\n\n## Database support\n\n### ActiveRecord\n\n```ruby\nclass CreateUsers \u003c ActiveRecord::Migration\n  def change\n    create_table :users do |t|\n      t.string :status\n      t.string :role\n\n      t.timestamps\n    end\n  end\nend\n\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], default: lambda { |user| StatusIdentifier.status_for_age(user.age).to_sym }\n\n  enumerize :role, in: [:user, :admin], default: :user\nend\n```\n\n:warning: By default, `enumerize` adds `inclusion` validation to the model. You can skip validations by passing `skip_validations` option. :warning:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], skip_validations: lambda { |user| user.new_record? }\n\n  enumerize :role, in: [:user, :admin], skip_validations: true\nend\n```\n\n### Mongoid\n\n```ruby\nclass User\n  include Mongoid::Document\n  extend Enumerize\n\n  field :role\n  enumerize :role, in: [:user, :admin], default: :user\nend\n```\n\n### MongoMapper\n\n```ruby\nclass User\n  include MongoMapper::Document\n  extend Enumerize\n\n  key :role\n  enumerize :role, in: [:user, :admin], default: :user\nend\n```\n\n---\n\n## I18n Support\n\n```ruby\nen:\n  enumerize:\n    user:\n      status:\n        student: \"Student\"\n        employed: \"Employed\"\n        retired: \"Retiree\"\n```\n\nor if you use `status` attribute across several models you can use `defaults` scope:\n\n```ruby\nen:\n  enumerize:\n    defaults:\n      status:\n        student: \"Student\"\n        employed: \"Employed\"\n        retired: \"Retiree\"\n```\n\nYou can also pass `i18n_scope` option to specify scope (or array of scopes) storing the translations.\n\n```ruby\nclass Person\n  extend Enumerize\n  extend ActiveModel::Naming\n\n  enumerize :status, in: %w[student employed retired], i18n_scope: \"status\"\n  enumerize :roles, in: %w[user admin], i18n_scope: [\"user.roles\", \"roles\"]\n  enumerize :color, in: %w[green blue], i18n_scope: proc { |value| \"color\" }\nend\n\n# localization file\nen:\n  status:\n    student: \"Student\"\n    employed: \"Employed\"\n    retired: \"Retiree\"\n  user:\n    roles:\n      user: \"User\"\n  roles:\n    admin: \"Admin\"\n```\n\nNote that if you want to use I18n feature with plain Ruby object don't forget to extend it with `ActiveModel::Naming`:\n\n```ruby\nclass User\n  extend Enumerize\n  extend ActiveModel::Naming\nend\n```\n\n### I18n Helper Methods\n\n#### \\*\\_text / .text\n\nAttribute's I18n text value:\n\n```ruby\n@user.status_text # or @user.status.text\n```\n\n#### values\n\nList of possible values for an enumerized attribute:\n\n```ruby\nUser.status.values # or User.enumerized_attributes[:status].values\n# =\u003e ['student', 'employed', 'retired']\n```\n\n#### I18n text values\n\nList of possible I18n text values for an enumerized attribute:\n\n```ruby\nUser.status.values.collect(\u0026:text)\n# =\u003e ['Student', 'Employed', 'Retiree']\n```\n\n#### Form example\n\nUse it with forms (it supports `:only` and `:except` options):\n\n```erb\n\u003c%= form_for @user do |f| %\u003e\n  \u003c%= f.select :status, User.status.options %\u003e\n\u003c% end %\u003e\n```\n\n---\n\n## Boolean Helper Methods\n\n### Basic\n\n```ruby\nuser.status = :student\nuser.status.student? #=\u003e true\nuser.status.retired? #=\u003e false\n```\n\n### Predicate Methods\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: %w(student employed retired), predicates: true\nend\n\nuser = User.new\n\nuser.student?  # =\u003e false\nuser.employed? # =\u003e false\n\nuser.status = :student\n\nuser.student?  # =\u003e true\nuser.employed? # =\u003e false\n```\n\n: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](https://github.com/brainspec/enumerize/issues/235). :warning:\n\n#### Predicate Prefixes\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: %w(student employed retired), predicates: { prefix: true }\nend\n\nuser = User.new\nuser.status = 'student'\nuser.status_student? # =\u003e true\n```\n\nUse `:only` and `:except` options to specify what values create predicate methods for.\n\n---\n\n## Optimzations and Tips\n\n### Extendable Module\n\nTo make some attributes shared across different classes it's possible to define them in a separate module and then include it into classes:\n\n```ruby\nmodule RoleEnumerations\n  extend Enumerize\n\n  enumerize :roles, in: %w[user admin]\nend\n\nclass Buyer\n  include RoleEnumerations\nend\n\nclass Seller\n  include RoleEnumerations\nend\n```\n\n### Customizing Enumerize Value\n\nIt'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:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n\n  enumerize :role, in: { user: 1, admin: 2 }\nend\n\nuser = User.new\nuser.role = :user\nuser.role #=\u003e 'user'\nuser.role_value #=\u003e 1\n\nUser.role.find_value(:user).value #=\u003e 1\nUser.role.find_value(:admin).value #=\u003e 2\n```\n\n### ActiveRecord scopes:\n\n#### Basic\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n  enumerize :role, in: [:user, :admin], scope: true\n  enumerize :status, in: { student: 1, employed: 2, retired: 3 }, scope: :having_status\nend\n\nUser.with_role(:admin)\n# SELECT \"users\".* FROM \"users\" WHERE \"users\".\"role\" IN ('admin')\n\nUser.without_role(:admin)\n# SELECT \"users\".* FROM \"users\" WHERE \"users\".\"role\" NOT IN ('admin')\n\nUser.having_status(:employed).with_role(:user, :admin)\n# SELECT \"users\".* FROM \"users\" WHERE \"users\".\"status\" IN (2) AND \"users\".\"role\" IN ('user', 'admin')\n```\n\n#### Shallow Scopes\n\nAdds named scopes to the class directly.\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n  enumerize :status, in: [:student, :employed, :retired], scope: :shallow\n  enumerize :role, in: { user: 1, admin: 2 }, scope: :shallow\nend\n\nUser.student\n# SELECT \"users\".* FROM \"users\" WHERE \"users\".\"status\" = 'student'\n\nUser.admin\n# SELECT \"users\".* FROM \"users\" WHERE \"users\".\"role\" = 2\n```\n\n:warning: It is not possible to define a scope when using the `:multiple` option. :warning:\n\n### Array-like Attributes\n\nArray-like attributes with plain ruby objects:\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :interests, in: [:music, :sports], multiple: true\nend\n\nuser = User.new\nuser.interests \u003c\u003c :music\nuser.interests \u003c\u003c :sports\n```\n\nand with ActiveRecord:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  extend Enumerize\n\n  serialize :interests, Array\n  enumerize :interests, in: [:music, :sports], multiple: true\nend\n```\n\nget an array of all text values:\n\n```ruby\n@user.interests.texts # shortcut for @user.interests.map(\u0026:text)\n```\n\nAlso, the reader method can be overridden, referencing the enumerized attribute value using `super`:\n\n```ruby\ndef status\n  if current_user.admin?\n    \"Super #{super}\"\n  else\n    super\n  end\nend\n```\n\n---\n\n## Forms\n\n### SimpleForm\n\nIf you are using SimpleForm gem you don't need to specify input type (`:select` by default) and collection:\n\n```erb\n\u003c%= simple_form_for @user do |f| %\u003e\n  \u003c%= f.input :status %\u003e\n\u003c% end %\u003e\n```\n\nand if you want it as radio buttons:\n\n```erb\n\u003c%= simple_form_for @user do |f| %\u003e\n  \u003c%= f.input :status, as: :radio_buttons %\u003e\n\u003c% end %\u003e\n```\n\nPlease 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.\n\n### Formtastic\n\nIf you are using Formtastic gem you also don't need to specify input type (`:select` by default) and collection:\n\n```erb\n\u003c%= semantic_form_for @user do |f| %\u003e\n  \u003c%= f.input :status %\u003e\n\u003c% end %\u003e\n```\n\nand if you want it as radio buttons:\n\n```erb\n\u003c%= semantic_form_for @user do |f| %\u003e\n  \u003c%= f.input :status, as: :radio %\u003e\n\u003c% end %\u003e\n```\n\n---\n\n## Testing\n\n### RSpec\n\nAlso you can use builtin RSpec matcher:\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired]\nend\n\ndescribe User do\n  it { should enumerize(:status) }\n\n  # or with RSpec 3 expect syntax\n  it { is_expected.to enumerize(:status) }\nend\n```\n\n#### Qualifiers\n\n##### in\n\nUse `in` to test usage of the `:in` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired]\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired) }\nend\n```\n\nYou can test enumerized attribute value using custom values with the `in`\nqualifier.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :role, in: { user: 0, admin: 1 }\nend\n\ndescribe User do\n  it { should enumerize(:role).in(user: 0, admin: 1) }\nend\n```\n\n##### with_default\n\nUse `with_default` to test usage of the `:default` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :role, in: [:user, :admin], default: :user\nend\n\ndescribe User do\n  it { should enumerize(:user).in(:user, :admin).with_default(:user) }\nend\n```\n\n##### with_i18n_scope\n\nUse `with_i18n_scope` to test usage of the `:i18n_scope` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], i18n_scope: 'status'\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_i18n_scope('status') }\nend\n```\n\n##### with_predicates\n\nUse `with_predicates` to test usage of the `:predicates` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], predicates: true\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(true) }\nend\n```\n\nYou can text prefixed predicates with the `with_predicates` qualifiers.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], predicates: { prefix: true }\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_predicates(prefix: true) }\nend\n```\n\n##### with_scope\n\nUse `with_scope` to test usage of the `:scope` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], scope: true\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_scope(true) }\nend\n```\n\nYou can test a custom scope with the `with_scope` qualifiers.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed], scope: :employable\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_scope(scope: :employable) }\nend\n```\n\n##### with_multiple\n\nUse `with_multiple` to test usage of the `:multiple` option.\n\n```ruby\nclass User\n  extend Enumerize\n\n  enumerize :status, in: [:student, :employed, :retired], multiple: true\nend\n\ndescribe User do\n  it { should enumerize(:status).in(:student, :employed, :retired).with_multiple(true) }\nend\n```\n\n### Minitest with Shoulda\n\nYou can use the RSpec matcher with shoulda in your tests by adding two lines in your `test_helper.rb` inside `class ActiveSupport::TestCase` definition:\n\n```ruby\nclass ActiveSupport::TestCase\n  ActiveRecord::Migration.check_pending!\n\n  require 'enumerize/integrations/rspec'\n  extend Enumerize::Integrations::RSpec\n\n  ...\nend\n```\n\n### Other Integrations\n\nEnumerize integrates with the following automatically:\n\n- [RailsAdmin](https://github.com/sferik/rails_admin/)\n\n---\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","funding_links":[],"categories":["Active Record","Active Record Plugins","Ruby","ORM/ODM Extensions","模型","WebSocket"],"sub_categories":["Omniauth","Active Record Enumerations"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrainspec%2Fenumerize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrainspec%2Fenumerize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrainspec%2Fenumerize/lists"}