Module: EnumzFactory

Defined in:
lib/enumz/enumz_factory.rb

Class Method Summary collapse

Class Method Details

.create(name, data_elements, options) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'lib/enumz/enumz_factory.rb', line 7

def create(name, data_elements, options)
  name = if name.is_a? Symbol
    name.to_s.split('_').map(&:capitalize).join
  else
    raise ArgumentError, 'name must be of type symbol. e.g., "enum :my_name [:red, "yellow", ..]"'
  end

  create_module(name, process_data_elements(data_elements), options)
end

.create_module(name, data_elements, options) ⇒ Object

process_data_elements



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/enumz/enumz_factory.rb', line 42

def create_module(name, data_elements, options)
  # create a new module
  mod = Object.const_set(name.to_s, Module.new)

  # grab base methods from the new module,
  # which we'll delete at the end
  base_methods = mod.methods.clone.sort

  # the new module extends the BaseEnum module
  mod.extend BaseEnumz

  # set the data_elements property
  mod.instance_variable_set('@data_elements', data_elements)

  # set the options property
  mod.instance_variable_set('@options', options)

  # add a constant for each enum name/value
  data_elements.each { |k,v|
    raise NameError, "#{k.inspect} is not a valid enum name!" unless /\A[a-zA-Z]/ =~ k.to_s
    mod.const_set(k.to_s.capitalize, v)
  }

  # remove all unnecessary defacto ruby module methods
  # in order to avoid potential conflicts with enum names
  # EX: module.name vs enum.name
  #     module.clone vs enum.clone
  base_methods.each do |m|
    mod.instance_eval "undef :#{m}" unless (m.match(/^__/)) or BaseEnumz::RESERVED_METHOD_NAMES.include?(m)
  end

  mod
end

.process_data_elements(data_elements) ⇒ Object

create

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/enumz/enumz_factory.rb', line 17

def process_data_elements(data_elements)
  data_elements = if data_elements.is_a? Array
    # if an array, then convert to a hash
    # 1) the hash keys = array data_elements
    # 2) the hash data_elements correspond to the array value's index position
    # 3) the hash keys are symbols
    Hash[*data_elements.reduce([]) {|result, a| result << a.to_s.to_sym; result << (result.count / 2) + 1 }.flatten]
  elsif data_elements.is_a? Hash
    # ensure the values are unique
    raise ArgumentError, 'values must be unique' unless data_elements.values.count == data_elements.values.uniq.count

    # ensure that the keys are symbols
    Hash[ data_elements.map { |k, v| [ k.to_s.to_sym, v ] }]
  else
    raise ArgumentError, 'data_elements must be either an array or a hash, e.g., "enum :my_name {:red => 1, "yellow" => 2, ..}"'
  end

  # raise an exception if an enum name is a reserved method name
  intersection = (data_elements.keys & BaseEnumz::RESERVED_METHOD_NAMES)
  raise ArgumentError, "enum name #{intersection[0]} is a reserved ruby method name" unless intersection.empty?

  # freeze the hash so no modifications can be made at a later time
  data_elements.freeze
end