Type-safe enumerations with ordinals, custom values, and pattern matching
gem install philiprehberger-enumType-safe enumerations with ordinals, custom values, and pattern matching
Add to your Gemfile:
gem "philiprehberger-enum"
Or install directly:
gem install philiprehberger-enum
require "philiprehberger/enum"
class Status < Philiprehberger::Enum
member :draft
member :published
member :archived
end
Status::DRAFT.name # => :draft
Status::DRAFT.ordinal # => 0
Status.members # => [DRAFT, PUBLISHED, ARCHIVED]
class HttpCode < Philiprehberger::Enum
member :ok, value: 200
member :not_found, value: 404
member :server_error, value: 500
end
HttpCode::OK.value # => 200
HttpCode.from_value(404) # => HttpCode::NOT_FOUND
Status.from_name(:draft) # => Status::DRAFT
Status.from_string('draft') # => Status::DRAFT
Status.valid?(:draft) # => true
Status.valid?(:unknown) # => false
Enum classes include Enumerable, so you can iterate, map, select, etc.:
Status.each { |member| puts member.name }
Status.map(&:name) # => [:draft, :published, :archived]
Status.select { |m| m.ordinal > 0 } # => [PUBLISHED, ARCHIVED]
Status.to_a # => [DRAFT, PUBLISHED, ARCHIVED]
Status.min # => DRAFT
Status.to_h # => { draft: nil, published: nil, archived: nil }
HttpCode.to_h # => { ok: 200, not_found: 404, server_error: 500 }
HttpCode.members_by_value # => { 200 => OK, 404 => NOT_FOUND, 500 => SERVER_ERROR }
Status.size # => 3
Status.count # => 3
fetch and fetch_by_value raise an error instead of returning nil:
Status.fetch(:draft) # => Status::DRAFT
Status.fetch(:unknown) # raises Philiprehberger::Enum::Error
HttpCode.fetch_by_value(200) # => HttpCode::OK
HttpCode.fetch_by_value(999) # raises Philiprehberger::Enum::Error
HttpCode.names # => [:ok, :not_found, :server_error]
HttpCode.values # => [200, 404, 500]
Status.first # => Status::DRAFT
Status.last # => Status::ARCHIVED
slice returns members matching the given names, silently skipping any that are unknown:
Status.slice(:draft, :archived) # => [Status::DRAFT, Status::ARCHIVED]
Status.slice(:draft, :nonexistent) # => [Status::DRAFT]
Status.slice(:archived, :draft) # => [Status::ARCHIVED, Status::DRAFT]
sample returns a random member. Pass an integer to get an array:
Status.sample # => Status::DRAFT (random)
Status.sample(2) # => [Status::PUBLISHED, Status::ARCHIVED] (random)
from_name tries an exact match first, then falls back to case-insensitive:
Status.from_name(:draft) # => Status::DRAFT (exact match)
Status.from_name("DRAFT") # => Status::DRAFT (case-insensitive)
Status.from_name("Draft") # => Status::DRAFT (case-insensitive)
Members are comparable by ordinal:
Status::DRAFT < Status::PUBLISHED # => true
Status.members.sort # sorted by declaration order
case Status::DRAFT
in { name: :draft }
'is draft'
in { name: :published }
'is published'
end
Status::DRAFT.to_s # => "draft"
Status::DRAFT.to_json # => '{"name":"draft","ordinal":0,"value":null}'
Philiprehberger::Enum (base class)| Method | Description |
|---|---|
.member(name, value: nil) | Define a new enum member with optional custom value |
.members | Return all members in declaration order |
.each | Yield each member (includes Enumerable) |
.to_h | Return { name_symbol => value } hash |
.members_by_value | Return { value => member } reverse lookup hash |
.size / .count | Return the number of defined members |
.names | Return a frozen array of member name symbols |
.values | Return a frozen array of member values |
.first / .last | Return the first or last declared member |
.fetch(name) | Strict lookup by name; raises Error if not found |
.fetch_by_value(val) | Strict lookup by value; raises Error if not found |
.from_name(name) | Look up by name (case-insensitive fallback) |
.from_string(string) | Look up a member by string name |
.from_value(val) | Look up a member by custom value |
.from_ordinal(ord) | Look up a member by ordinal position (returns nil if out of range) |
.fetch_by_ordinal(ord) | Same as from_ordinal but raises Error if not found |
.slice(*names) | Return members matching the given symbol names, skipping unknowns |
.sample(n = nil) | Return a random member, or array of n random members |
.valid?(name) | Check if a name is a valid member |
#name | Return the member name as a symbol |
#ordinal | Return the ordinal position |
#value | Return the custom value, or nil |
#to_s | Return the member name as a string |
#to_json | Serialize to JSON with name, ordinal, and value |
#deconstruct_keys(keys) | Pattern matching support |
#<=>(other) | Compare by ordinal |
bundle install
bundle exec rspec
bundle exec rubocop
If you find this project useful: