Module: AttributeEnum::ClassMethods

Defined in:
lib/attribute_enum.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#enumsObject (readonly)

Returns the value of attribute enums.



13
14
15
# File 'lib/attribute_enum.rb', line 13

def enums
  @enums
end

Instance Method Details

#enum(enumerated, values) ⇒ Object

Turns a dot-accessible class attribute to an enum (a.k.a bytefield). Class must have read’n’write attribute named [what’s being enumerated].

Examples:


class Payment
  include AttributeEnum
  attr_accessor :status

  def initialize(status = 0)
    @status = status
  end

  enum :status, [ :active, :inactive ]
end

payment = Payment.new

payment.get_status # => :active
payment.inactive? # => false
payment.set_status(:inactive) # => true
payment.set_status(:invalid) # => ArgumentError('unknown value invalid')
payment.active? # => false
payment.active! # => true
payment.statuses # => [:active, :inactive]
payment.get_statuses # => [:active, :inactive]

Payment.statuses # => [:active, :inactive]
Payment.get_statuses # => [:active, :inactive]
Payment.get_status(1) # => :inactive
Payment.get_status(:active) # => 0
Payment.get_status('invalid') # => ArgumentError('valid argument is either Fixnum or Symbol')


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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/attribute_enum.rb', line 48

def enum(enumerated, values)
  if values.is_a? Hash
    values.each do |key,val|
      raise ArgumentError, "index should be numeric, #{key} provided wich it's a #{key.class}" unless key.is_a? Fixnum
      raise ArgumentError "value should be a symbol, #{val} provided wich it's a #{val.class}" unless val.is_a? Symbol
    end
  elsif values.is_a? Array
    values = Hash[values.map.with_index { |v, i| [i,v] }]
  else
    raise ArgumentError, "#enum expects the second argument to be an array of symbols or a hash like { index => :value }"
  end

  # Symbolize values
  #
  values.each do |key, val|
    s_key = key.to_s
    values[key]   = values[key].to_sym   if values[key]
    values[s_key] = values[s_key].to_sym if values[s_key]
  end

  pluralized = enumerated.to_s.pluralize

  # ###
  # Instance methods
  # ###

  # obj.set_status :active
  #
  define_method "set_#{enumerated}" do |value|
    index = self.class.enums[enumerated].rassoc(value)
    raise ArgumentError.new("unknown value #{ value }") unless (index && (index = index.first))
    self.send("#{enumerated}=", index)
    true
  end

  # obj.get_status # => :active
  #
  define_method "get_#{enumerated}" do
    self.class.enums[enumerated].fetch(self.send(enumerated), nil)
  end

  values.each do |key, value|
    # obj.inactive? # => false
    #
    define_method "#{value}?" do
      self.send("get_#{enumerated}") == value
    end

    # obj.inactive! # => true
    #
    define_method "#{value}!" do
      self.send("set_#{enumerated}", value)
    end
  end

  # obj.statuses # => [:active, :inactive]
  #
  define_method pluralized do
    self.class.enums[enumerated].map{ |k, v| v }
  end

  # obj.get_statuses # => [:active, :inactive]
  #
  alias_method "get_#{pluralized}", pluralized

  # ###
  # Class methods
  # ###

  # Obj.statuses # => [:active, :inactive]
  #
  define_singleton_method pluralized do
    self.enums[enumerated].map{ |k, v| v }
  end

  # Obj.get_statuses # => [:active, :inactive]
  #
  singleton_class.class_eval do
    alias_method "get_#{pluralized}", pluralized
  end

  # Obj.get_status(0) # => :active
  # Obj.get_status(:active) # => 0
  #
  define_singleton_method "get_#{enumerated}" do |arg|
    if arg.is_a? Fixnum
      self.enums[enumerated].fetch(arg, nil)
    elsif arg.is_a? Symbol
      key = self.enums[enumerated].rassoc(arg)
      key ? key[0] : nil
    else
      raise ArgumentError.new('valid argument is either Fixnum or Symbol')
    end
  end

  # Fin
  enums[enumerated] = values
end