Class: Enum

Inherits:
Object
  • Object
show all
Extended by:
Enumerable, Forwardable
Includes:
Comparable
Defined in:
lib/enum.rb

Overview

An Enum is a class with a predefinite set of instances. Instances have an implicit ordering (dependent on the order of definition), can be retrieved by key and be enumerated.

Examples:

Basic usage

class Foo < Enum
  value :A
  value :B
end

Foo.inspect  # => Foo(A, B)

# Instances are accessible as constants
Foo::A.class # => Foo
Foo::B.class # => Foo
Foo::C       # => raises NameError

# Enumerated values are implicitly ordered, depending on order of definition
Foo::A == Foo::B # => false
Foo::A < Foo::B  # => true

# Instances can be retrieved by key
Foo[:a]      # => Foo::A
Foo['a']     # => Foo::A
Foo.for('A') # => Foo::A
Foo.for('X') # => raises KeyError

Foo.new      # => raises an error

# Helper methods
Foo.a        # => Foo::A
Foo.b        # => Foo::B

Foo::A.a?    # => true
Foo::A.b?    # => false

Creating enums with a shortcut

Bar = Enum.create(:a, :b, :c) # => Bar(A, B, C)

Custom initializer

class Foobar < Enum
  def initialize(name)
    @name = name
  end

  attr_reader :name

  value :A, 'foo'
  value :B, 'bar'
end

Foobar::A.name # => 'foo'
Foobar::B.name # => 'bar'

Inheritance

class Base < Enum
  value :A
  value :B
end

class Child < Base
  value :C
end

Base.inspect # => Base(A, B)
Child.inspect # => Child(A, B, C)

# NOTE: If you reopen the base class later, the changes won't be reflected in the child.
# The values to inherit are evaluated at the time of the class definition

Advanced inheritance with custom initializer

class Base < Enum
  def initialize(name)
    @name = name
  end

  attr_reader :name

  value :A, 'foo'
  value :B, 'bar'
end

class Child < Base
  def initialize(name, number)
    super(name)
    @number = number
  end

  def initialize_from_superclass(superclass_enum_value)
    super # default behavior is to copy all the instance variables
    @number = superclass_enum_value.ord + 1
  end

  attr_reader :number

  value :C, 'baz', 3
end

Child::C.name   # => 'baz'
Child::C.number # => 3

Child::B.name   # => 'bar'
Child::B.number # => 2

Defined Under Namespace

Classes: DuplicateEnumKey

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#keySymbol (readonly) Also known as: to_sym

The key of this value in the enumeration

Returns:

  • (Symbol)

115
116
117
# File 'lib/enum.rb', line 115

def key
  @key
end

#ordInteger (readonly)

Relative ordering index of the instance

Returns:

  • (Integer)

119
120
121
# File 'lib/enum.rb', line 119

def ord
  @ord
end

Class Method Details

.const_missing(sym) ⇒ Object


197
198
199
200
201
# File 'lib/enum.rb', line 197

def const_missing(sym)
  self.for(sym)
rescue
  super
end

.create(*keys) ⇒ Class

Returns:

  • (Class)

189
190
191
192
193
# File 'lib/enum.rb', line 189

def create(*keys)
  Class.new(self).tap do |enum|
    keys.each { |key| enum.value(key) }
  end
end

.for(value) ⇒ self Also known as: []

Parameters:

  • value (String, Symbol, Class)

Returns:

  • (self)

Raises:

  • (KeyError)

    if there is no enumerated value with the specified key


182
183
184
185
186
# File 'lib/enum.rb', line 182

def for(value)
  return value if value.is_a? self.class
  enum_key = value.nil? ? nil : value.upcase.to_sym
  values.find(proc { raise KeyError, "Enumerated value not found: #{value.inspect}" }) { |v| v.key == enum_key }
end

.inspectObject


252
253
254
# File 'lib/enum.rb', line 252

def inspect
  "#{name || 'Enum'}(#{values.map(&:to_s).join(', ')})"
end

Instance Method Details

#<=>(other) ⇒ Object

Objects are compared based on their implicit ordering (order of definition).

See Also:


152
153
154
155
# File 'lib/enum.rb', line 152

def <=>(other)
  other = self.class.for(other) if other.is_a?(Symbol) || other.is_a?(String)
  ord <=> other.ord
end

#==(other) ⇒ Boolean Also known as: eql?

Tests the objects for equality. Two enum values are considered equal if they have the same key and belong to the same enumeration.

Parameters:

  • other (Object)

    object to compare to

Returns:

  • (Boolean)

140
141
142
143
144
# File 'lib/enum.rb', line 140

def ==(other)
  return false if other.nil?
  other = self.class.for(other) if other.is_a?(Symbol) || other.is_a?(String)
  instance_of?(other.class) && key == other.key
end

#hashObject


130
131
132
# File 'lib/enum.rb', line 130

def hash
  key.to_s.hash
end

#inspectString

Returns a representation of this instance (e.g. `EnumName::VALUE_1`)

Returns:

  • (String)

123
124
125
# File 'lib/enum.rb', line 123

def inspect
  "#{self.class.name || 'Enum'}::#{key}"
end