EnumFields

Enhanced enum-like fields for ActiveRecord models with metadata support

Requirements

  • Ruby >= 2.7.6
  • Rails >= 6.0 (ActiveRecord and ActiveSupport)

Installation

Add this line to your application's Gemfile:

gem 'enum_fields'

And then execute:

bundle install

Usage

Basic Setup

Include the EnumFields module in your ApplicationRecord:

class ApplicationRecord < ActiveRecord::Base
  include EnumFields

  self.abstract_class = true
end

Now all models inheriting from ApplicationRecord can use enum_field.

Defining Enum Fields

class Campaign < ApplicationRecord
  enum_field :stage, {
    pending: {
      value: 'pending',
      label: 'Pending',
      icon: 'clock',
      color: 'yellow',
      tooltip: 'Campaign is awaiting processing',
    },
    processing: {
      value: 'processing',
      label: 'Processing',
      icon: 'cog',
      color: 'blue',
      tooltip: 'Campaign is being processed',
    },
    shipped: {
      value: 'shipped',
      label: 'Shipped',
      icon: 'truck',
      color: 'green',
      tooltip: 'Campaign has been shipped',
    },
    delivered: {
      value: 'delivered',
      label: 'Delivered',
      icon: 'check',
      color: 'green',
      tooltip: 'Campaign has been delivered',
    },
  }
end

Array Definition (Simple)

class Task < ApplicationRecord
  enum_field :priority, ['low', 'medium', 'high']
end

This automatically generates:

{
  low: {
    value: 'low',
    label: 'low',
  },
  medium: {
    value: 'medium',
    label: 'medium',
  },
  high: {
    value: 'high',
    label: 'high',
  },
}

Custom Column Mapping

If your accessor name differs from your column name:

class User < ApplicationRecord
  enum_field :role, definitions, column: :user_role
end

Generated Methods

For an enum field defined as:

class Campaign < ApplicationRecord
  enum_field :stage, {
    draft: {
      value: 'draft',
      label: 'Draft',
      icon: 'file',
      color: 'gray',
    },
    scheduled: {
      value: 'scheduled',
      label: 'Scheduled',
      icon: 'calendar',
      color: 'blue',
    },
    completed: {
      value: 'completed',
      label: 'Completed',
      icon: 'check',
      color: 'green',
    },
  }
end

Class Methods

# Returns the definitions as an HashWithIndifferentAccess
Campaign.stages

# Returns the count of definitions
Campaign.stages_count # 3

# Returns the values of the definitions
Campaign.stages_values # ['draft', 'scheduled', 'completed']

# Returns the options for form helpers
Campaign.stages_options # [['Draft', 'draft'], ['Scheduled', 'scheduled'], ['Completed', 'completed']]

Instance Getter/Setter

If the accessor name differs from the column name, getter and setter methods are defined for the accessor.

campaign.stage # 'draft'
campaign.stage = 'scheduled'
campaign.stage # 'scheduled'
  • campaign.stage - Get the current stage value
  • campaign.stage = 'scheduled' - Set the stage value

Metadata Methods

The gem automatically creates accessor methods for all properties defined in your enum definitions.

  • value (required) - The actual value stored in the database
  • label (auto-generated if not provided) - A human-readable label

Any additional properties you define (like icon, color, tooltip, etc.) will also get dedicated accessor methods automatically.

# Returns the full metadata hash for current value
campaign.
# => { value: 'draft', label: 'Draft', icon: 'file', color: 'gray' }

# Access individual properties
campaign.stage_value # 'draft'
campaign.stage_label # 'Draft'
campaign.stage_icon  # 'file'
campaign.stage_color # 'gray'

Inquiry Methods

# Returns true if the current value is 'draft'
campaign.draft_stage?

# Returns true if the current value is 'scheduled'
campaign.scheduled_stage?

# Returns true if the current value is 'completed'
campaign.completed_stage?

Scopes

# Returns all campaigns with draft stage
Campaign.draft_stage

# Returns all campaigns with scheduled stage
Campaign.scheduled_stage

# Returns all campaigns with completed stage
Campaign.completed_stage

Validation

Automatically validates that the column value is included in the defined values (with allow_nil: true).

Custom Properties

You can add any custom properties to your definitions, and the gem will automatically create accessor methods for them:

class Ticket < ApplicationRecord
  enum_field :priority, {
    low: {
      value: 'low',
      label: 'Low Priority',
      sla_hours: 72,
      notify_manager: false,
    },
    high: {
      value: 'high',
      label: 'High Priority',
      sla_hours: 4,
      notify_manager: true,
    },
  }
end

# Access custom properties directly via generated methods
ticket.priority_sla_hours      # 72
ticket.priority_notify_manager # false

# Or access via metadata hash
ticket.[:sla_hours]      # 72
ticket.[:notify_manager] # false

Development

After checking out the repo, run:

bundle install

Run the test suite:

bundle exec rspec

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/kinnell/enum_fields.

License

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