Class: EnumX

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/enum_x.rb,
lib/enum_x/dsl.rb,
lib/enum_x/value.rb,
lib/enum_x/railtie.rb,
lib/enum_x/version.rb,
lib/enum_x/value_list.rb

Overview

Utility class representing an enumeration of options to choose from. This can be used in models to make a field have a certain number of allowed options.

Enums are defined in configuration files which are loaded from load paths (see EnumX.load_paths).

EnumX file format

EnumX files are YAML files defining enumerations in the following format:

<name>: [ <value>, <value, ... ]

E.g.

statuses: [ draft, sent, returned ]

Extra formats

EnumX values are designed to be converted to various formats. By default, they simply support a name, which is the value you specify in the YAML files. They also respond to any method starting with ‘to_’, e.g. to_string, to_json, to_legacy. These return the name of the value, unless otherwise specified explicitly when being defined.

If you want to provide extra formats in the YAML, you may indicate them as follows:

statuses: [ { value: 'draft', legacy: 'new' }, sent, { value: 'returned', legacy: 'back' } ]

Now, the following will all be true:

EnumX.statuses[:draft].value == 'draft'
EnumX.statuses[:draft].symbol == :draft
# => #symbol always returns the value converted to a Symbol
EnumX.statuses[:draft].to_legacy == 'new'
EnumX.statuses[:sent].value == 'sent'
EnumX.statuses[:sent].symbol == :sent
EnumX.statuses[:sent].to_legacy == 'sent'
# => because no explicit value for the 'legacy' format was specified

Defined Under Namespace

Modules: DSL Classes: Railtie, Registry, Value, ValueHash, ValueList

Constant Summary collapse

VERSION =
'1.1.0'

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, values) ⇒ EnumX

Initializes a new EnumX instance.

Parameters:

  • name (#to_s)

    The name of the enum. This is used to load translations. See EnumX::Value#to_s.

  • values (Enumerable)

    The values for the enumeration. Each item is passed to EnumX::Value.new.



191
192
193
194
195
196
197
198
# File 'lib/enum_x.rb', line 191

def initialize(name, values)
  @name = name.to_s

  @values = ValueHash.new
  values.each do |value|
    add_value!(value)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)



314
315
316
317
318
319
320
321
# File 'lib/enum_x.rb', line 314

def method_missing(method, *args, &block)
  if method =~ /^value_with_(.*)$/
    raise ArgumentError, "`#{method}' accepts one argument, #{args.length} given" unless args.length == 1
    value_with_format $1, args.first
  else
    super
  end
end

Class Attribute Details

.loaderObject

Allows overriding of the load handler.

Specify an object that responds to load_enums_from(file, file_type) where file is a file name, and file_type is either :yaml or :ruby. Alternatively, a block may be specified that will receive these parameters.

The method does not have to return anything, but should use calls to define to actually define the enums.

By default, the loader parses the YAML file as a flat Hash, where the keys are enum names, and the values are arrays containing the values.

Usage

EnumX.loader = proc do |file, file_type|
  if file_type == :ruby
    load file
  else
    ... # Process the YAML file here.
  end
end


122
123
124
# File 'lib/enum_x.rb', line 122

def loader
  @loader
end

Instance Attribute Details

#nameString (readonly)

Returns The name of the enum.

Returns:

  • (String)

    The name of the enum.



205
206
207
# File 'lib/enum_x.rb', line 205

def name
  @name
end

#valuesArray<EnumX::Value> (readonly) Also known as: to_ary, to_a

Returns All allowed enum values.

Returns:



209
210
211
# File 'lib/enum_x.rb', line 209

def values
  @values.values
end

Class Method Details

.[](name) ⇒ Object

Retrieves an enum by name.



96
97
98
99
# File 'lib/enum_x.rb', line 96

def [](name)
  load_enums unless @registry
  registry[name]
end

.define(name, values) ⇒ Object

Defines a new enum with the given values.

See Also:



86
87
88
# File 'lib/enum_x.rb', line 86

def define(name, values)
  registry[name.to_s] = new(name, values)
end

.find(klass, name) ⇒ Object

Finds an enum with the given name on a class. TODO: Spec



273
274
275
276
277
278
# File 'lib/enum_x.rb', line 273

def self.find(klass, name)
  return nil unless klass

  enum = klass.send(name) if klass.respond_to?(name) rescue nil
  enum if enum.is_a?(EnumX)
end

.load_pathsObject



80
81
82
# File 'lib/enum_x.rb', line 80

def load_paths
  @load_paths ||= []
end

.load_paths=(paths) ⇒ Object

An array of EnumX load paths.

Examples:

Add some enum load paths

EnumX.load_paths += Dir[ Rails.root + 'config/enums/**/*.yml' ]


77
78
79
# File 'lib/enum_x.rb', line 77

def load_paths=(paths)
  @load_paths = Array.wrap(paths)
end

.undefine(name) ⇒ Object

Undefines an enum.



91
92
93
# File 'lib/enum_x.rb', line 91

def undefine(name)
  registry.delete name.to_s
end

Instance Method Details

#[](key) ⇒ Object

Obtains a value by its key.



226
227
228
# File 'lib/enum_x.rb', line 226

def [](key)
  @values[key]
end

#dupObject

Creates a duplicate of this enum.



240
241
242
# File 'lib/enum_x.rb', line 240

def dup
  EnumX.new(name, values)
end

#extend!(*values) ⇒ Object

Adds the given values to the enum



255
256
257
# File 'lib/enum_x.rb', line 255

def extend!(*values)
  values.each { |value| add_value!(value) }
end

#i18n_scopeObject

The I18n scope for this enum. Override this to provide customization. Default: enums.<name>



264
265
266
# File 'lib/enum_x.rb', line 264

def i18n_scope
  [ :enums, name ]
end

#only(*values) ⇒ Object

Creates a duplicate of this enumeration but with only the given values.



250
251
252
# File 'lib/enum_x.rb', line 250

def only(*values)
  EnumX.new(name, self.values.select{|v| values.include?(v)})
end

#value_with_format(format, search) ⇒ Object

Finds an enum value by the given format.

Example

Given the following enum:

@enum = EnumX.define(:my_enum,
  { :value => 'one', :number => '1' },
  { :value => 'two', :number => '2' }
)

You can now access the values like such:

@enum.value_with_format(:number, '1') # => @enum[:one]
@enum.value_with_format(:number, '2') # => @enum[:two]

Note that any undefined format for a value is defaulted to its value. Therefore, the following is also valid:

@enum.value_with_format(:unknown, 'one') # => @enum[:one]

You can also access values by a specific format using the shortcut ‘value_with_<format>’:

@enum.value_with_number('1')    # => @enum[:one]
@enum.value_with_unknown('one') # => @enum[:one]


308
309
310
# File 'lib/enum_x.rb', line 308

def value_with_format(format, search)
  values.find { |val| val.send(:"to_#{format}") == search }
end

#without(*values) ⇒ Object

Creates a clone of this enumeration but without the given values.



245
246
247
# File 'lib/enum_x.rb', line 245

def without(*values)
  EnumX.new(name, self.values.reject{|v| values.include?(v)})
end