Enhanced enum-like fields for ActiveRecord models with metadata support
- Ruby >= 2.7.6
- Rails >= 6.0 (ActiveRecord and ActiveSupport)
Add this line to your application's Gemfile:
gem 'enum_fields'And then execute:
bundle installInclude the EnumFields module in your ApplicationRecord:
class ApplicationRecord < ActiveRecord::Base
include EnumFields
self.abstract_class = true
endNow all models inheriting from ApplicationRecord can use enum_field.
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',
},
}
endclass Task < ApplicationRecord
enum_field :priority, ['low', 'medium', 'high']
endThis automatically generates:
{
low: {
value: 'low',
label: 'low',
},
medium: {
value: 'medium',
label: 'medium',
},
high: {
value: 'high',
label: 'high',
},
}If your accessor name differs from your column name:
class User < ApplicationRecord
enum_field :role, definitions, column: :user_role
endFor 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# 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']]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 valuecampaign.stage = 'scheduled'- Set the stage value
The gem automatically creates accessor methods for all properties defined in your enum definitions.
value(required) - The actual value stored in the databaselabel(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.stage_metadata
# => { 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'# 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?# 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_stageAutomatically validates that the column value is included in the defined values (with allow_nil: true).
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.priority_metadata[:sla_hours] # 72
ticket.priority_metadata[:notify_manager] # falseAfter checking out the repo, run:
bundle installRun the test suite:
bundle exec rspecBug reports and pull requests are welcome on GitHub at https://github.com/kinnell/enum_fields.
The gem is available as open source under the terms of the MIT License.