Class: Safe::Enum

Inherits:
Object
  • Object
show all
Defined in:
lib/enums/enum.rb,
lib/enums/enum_builder.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, value) ⇒ Enum

Returns a new instance of Enum.



12
13
14
15
16
17
# File 'lib/enums/enum.rb', line 12

def initialize( key, value )
  @key   = key
  @value = value
  self.freeze   ## make "immutable"
  self
end

Instance Attribute Details

#keyObject (readonly)

return a new Enum read-only class



9
10
11
# File 'lib/enums/enum.rb', line 9

def key
  @key
end

#valueObject (readonly)

Returns the value of attribute value.



10
11
12
# File 'lib/enums/enum.rb', line 10

def value
  @value
end

Class Method Details

.[](key) ⇒ Object

convenience alias for key



32
33
34
# File 'lib/enums/enum.rb', line 32

def self.[]( key )   ## convenience alias for key
  self.key( key )
end

.build_class(class_name, *args, **kwargs) ⇒ Object Also known as: new

meta-programming “macro” - build class (on the fly)



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
75
76
# File 'lib/enums/enum_builder.rb', line 10

def self.build_class( class_name, *args, **kwargs )

  if args.size > 0
    keys   = args
    values = (0...keys.size).to_a   # note: use ... (exclusive) range
    e = Hash[ keys.zip( values ) ]
  else
    ## assume kwargs
    e = kwargs
  end


  ## todo/fix:
  ##  check class name MUST start with uppercase letter

  ## check if all keys are symbols and follow the ruby id(entifier) naming rules
  e.keys.each do |key|
    if key.is_a?( Symbol ) && key =~ /\A[a-z][a-zA-Z0-9_]*\z/
    else
      raise ArgumentError.new( "[Enum] arguments to Enum.new must be all symbols following the ruby id naming rules; >#{key}< failed" )
    end
  end

  klass = Class.new( Enum )

  ## add self.new too - note: call/forward to "old" orginal self.new of Event (base) class
  klass.define_singleton_method( :new ) do |*new_args|
    old_new( *new_args )
  end

  e.each do |key,value|
    klass.class_eval( <<RUBY )
      #{key.upcase} = new( :#{key}, #{value} )

      def #{key}?
        self == #{key.upcase}
      end

      def self.#{key}
        #{key.upcase}
      end
RUBY
  end

  klass.class_eval( <<RUBY )
    def self.members
      @members ||= [#{e.keys.map {|key|key.upcase}.join(',')}].freeze
    end
RUBY

  ## note: use Kernel for "namespacing"
  ##   make all enums Kernel convenience converters (always) global
  ##     including uppercase methods (e.g. State(), Color(), etc.) does NOT work otherwise (with other module includes)

  ## add global convenience converter function
  ##  e.g. State(0) is same as State.convert(0)
  ##       Color(0) is same as Color.convert(0)
  Kernel.class_eval( <<RUBY )
    def #{class_name}( arg )
       #{class_name}.convert( arg )
    end
RUBY

  ## note: use Safe (module) and NO Object for namespacing
  ##   use include Safe to make all enums constants and machinery global
  Safe.const_set( class_name, klass )   ## returns klass (plus sets global constant class name)
end

.convert(arg) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/enums/enum.rb', line 58

def self.convert( arg )
  ## todo/check: support keys too - why? why not?
  ## e.g. Color(0), Color(1)
  ##      Color(:red), Color(:blue) - why? why not?
  ## note: will ALWAYS look-up by (member) index and NOT by value (integer number value might be different!!)
  members[ arg ]
end

.key(key) ⇒ Object



25
26
27
28
29
30
# File 'lib/enums/enum.rb', line 25

def self.key( key )
  ## note: returns nil now for unknown keys
  ##   use/raise IndexError or something - why? why not?
  @hash_by_key ||= Hash[ keys.zip( members ) ].freeze
  @hash_by_key[key]
end

.keysObject



20
21
22
23
# File 'lib/enums/enum.rb', line 20

def self.keys
  @keys ||= members.map {|member| member.key}.freeze
  @keys
end

.lengthObject

alias (as is the ruby tradition)



55
# File 'lib/enums/enum.rb', line 55

def self.length() size; end

.sizeObject



54
# File 'lib/enums/enum.rb', line 54

def self.size() keys.size; end

.value(value) ⇒ Object



42
43
44
45
46
47
# File 'lib/enums/enum.rb', line 42

def self.value( value )
  ## note: returns nil now for unknown values
  ##   use/raise IndexError or something - why? why not?
  @hash_by_value ||= Hash[ values.zip( members ) ].freeze
  @hash_by_value[value]
end

.valuesObject



37
38
39
40
# File 'lib/enums/enum.rb', line 37

def self.values
  @values ||= members.map {|member| member.value}.freeze
  @values
end

.zeroObject



50
# File 'lib/enums/enum.rb', line 50

def self.zero() members[0]; end

Instance Method Details

#zero?Boolean

Returns:

  • (Boolean)


51
# File 'lib/enums/enum.rb', line 51

def zero?() self == self.class.zero; end