EnumerateIt

repository·main·Indexed 43 days ago

https://github.com/lucascaton/enumerate_it

A Ruby gem for defining flexible enumerations as reusable classes with custom behavior. It supports standalone Ruby usage and deep integration with ActiveRecord via the `has_enumeration_for` macro, providing automatic inclusion and presence validations, I18n translation support, and the generation of predicate methods, mutators, and ActiveRecord scopes.

Tokens
5.2K
Snippets
20
Records
22
Agent score
55%

What's inside EnumerateIt

  1. How to use enumerations in ActiveRecord and non-ActiveRecord classes

    main

    EnumerateIt can be used in any Ruby class.

    For ActiveRecord models, use the has_enumeration_for macro directly.

    For non-ActiveRecord classes, you must extend EnumerateIt and provide an attr_accessor for the attribute before calling has_enumeration_for.

    If the enumeration class name is different from the attribute name, use the with: option to specify the class.

    # ActiveRecord instance
    class Person < ApplicationRecord
      has_enumeration_for :relationship_status
    end
    
    # Non-ActiveRecord instance
    class Person
      extend EnumerateIt
      attr_accessor :relationship_status
    
      has_enumeration_for :relationship_status
    end
    
    # Using a specific enumeration class
    class Person < ApplicationRecord
      has_enumeration_for :relationship_status, with: RelationshipStatus
    end
  2. Map enumeration values to legacy database integers

    main

    If you are working with a legacy database where enumeration values are stored as integers (e.g., in a lookup table), you can map the symbols to these specific values using associate_values in your enumeration class.

    You can also use sort_by :value to control the sorting order based on these mapped values.

    class RelationshipStatus < EnumerateIt::Base
      associate_values(
        single:   1,
        married:  2,
        divorced: 3
      )
    end
    
    # RelationshipStatus::MARRIED will return 2
  3. Use Rails generators for EnumerateIt

    main

    EnumerateIt provides a Rails generator to create both an enumeration class and its corresponding locale file automatically. Use the --help flag to see all available options.

    rails generate enumerate_it:enum --help
  4. Configure I18n for enumerations

    main

    EnumerateIt supports I18n for the _humanize method and the Enumeration#to_a method.

    Translations should be placed under the enumerations.<enumeration_name>.<key> path in your locale files.

    For namespaced enumerations (e.g., Design::Color), use the following structure in your YAML:

    enumerations:
      "design/color":
        blue: Azul
    # pt-BR locale
    pt-BR:
      enumerations:
        relationship_status:
          married: Casado
    # Usage
    p.relationship_status_humanize # => 'Casado'
    RelationshipStatus.t(RelationshipStatus::MARRIED) # => 'Casado'
  5. Configure I18n translations for enumerations

    main

    The translate method automatically looks for translations in the I18n library using a specific path pattern: enumerations.[class_name_underscored].[key_name_underscored]

    If no translation is found, it falls back to a humanized version of the symbol (e.g., :pending_review becomes Pending Review).

    # Example I18n YAML structure:
    # en:
    #   enumerations:
    #     status:
    #       pending: "Waiting for approval"
    #       active: "Currently running"
  6. Configure validations for enumerations

    main

    EnumerateIt provides built-in validations for classes that support them (like ActiveRecord):

    • Inclusion validation: Automatically added by has_enumeration_for. It ensures the value is part of the defined enumeration.
    • Presence validation: Enabled by passing required: true. This ensures the attribute is not nil.
    • Disabling validations: Pass skip_validation: true to prevent any validations from being added.

    Note: skip_validation: true takes precedence over required: true.

    # Inclusion validation (default)
    class Person < ApplicationRecord
      has_enumeration_for :relationship_status, with: RelationshipStatus
    end
    
    # Presence validation
    class Person < ApplicationRecord
      has_enumeration_for :relationship_status, with: RelationshipStatus, required: true
    end
    
    # Disable all validations
    class Person < ApplicationRecord
      has_enumeration_for :relationship_status, with: RelationshipStatus, skip_validation: true
    end
  7. Generate enumerations and locale files via Rails generator

    main

    The EnumerateIt Rails generator automates the creation of enumeration definition files and their corresponding i18n locale files. It places the enumeration logic in app/enumerations/ and the translation YAML in config/locales/.

    Usage

    Run the generator from your Rails terminal. You must provide the attributes for the enumeration. You can pass attributes as a simple list of names or as a hash mapping names to types.

    Options

    • --singular NAME: Provide a specific singular name for the i18n keys. If omitted, the generator derives the name from the input.
    • --lang LANGUAGE: Specify the language for the i18n file (defaults to en).
    # Example: Generating an enumeration named 'status' with specific values
    rails generate enumerate_it status:pending status:active status:archived
    
    # Example: Generating an enumeration with specific types and a custom singular name
    rails generate enumerate_it user_role --singular=user_role --lang=fr
  8. Integrate EnumerateIt with ActiveRecord

    main

    EnumerateIt automatically integrates with ActiveRecord::Base when Rails is loaded. By extending ActiveRecord::Base, the module makes enumeration capabilities available to all your models. This allows you to define enumerations directly within your ActiveRecord classes.

    # No manual setup required if using Rails/ActiveRecord;
    # EnumerateIt hooks into ActiveSupport.on_load(:active_record)
    # to extend ActiveRecord::Base automatically.
  9. Add custom behavior to enumerations

    main

    You can add custom logic and helper methods to your enumeration classes using the custom_helpers block. This allows you to encapsulate domain logic related to the enumeration values within the enumeration class itself.

    class RelationshipStatus < EnumerateIt::Base
      associate_values :single, :married, :divorced
    
      custom_helpers do
        def ever_married?(value)
          [MARRIED, DIVORCED].include?(value)
        end
      end
    end
  10. Configure enumeration sorting

    main

    By default, methods like to_a, to_json, and list return values in the order they were passed to associate_values. You can change this behavior using the sort_by class method.

    class RelationshipStatus < EnumerateIt::Base
      associate_values :single, :married
    
      sort_by :translation
    end
  11. Define custom helper methods in an enumeration

    main

    You can define custom logic within an enumeration class using a custom_helpers block. These methods become class methods on the enumeration class and, if create_helpers: true is used in the model, they also become instance methods on the model.

    If prefix: true is used in the model, the custom helpers will also be prefixed.

    class RelationshipStatus < EnumerateIt::Base
      associate_values :single, :married, :divorced
    
      custom_helpers do
        def ever_married?(value)
          [MARRIED, DIVORCED].include?(value)
        end
      end
    end
    
    # As class method
    RelationshipStatus.ever_married?(RelationshipStatus::MARRIED)
    
    # As model instance method (if create_helpers: true)
    person.ever_married?