Module: ActiveEnum::Extensions::ClassMethods

Defined in:
lib/active_enum/extensions.rb

Instance Method Summary collapse

Instance Method Details

#active_enum_for(attribute) ⇒ Object



53
54
55
# File 'lib/active_enum/extensions.rb', line 53

def active_enum_for(attribute)
  enumerated_attributes && enumerated_attributes[attribute.to_sym]
end

#define_active_enum_methods_for_attribute(attribute, options = {}) ⇒ Object



57
58
59
60
61
# File 'lib/active_enum/extensions.rb', line 57

def define_active_enum_methods_for_attribute(attribute, options={})
  define_active_enum_read_method(attribute) unless options[:skip_read]
  define_active_enum_write_method(attribute) unless options[:skip_write]
  define_active_enum_question_method(attribute) unless options[:skip_predicate]
end

#define_active_enum_question_method(attribute) ⇒ Object

Define question method to check enum value against attribute value

Example:

user.sex?(:male)


126
127
128
129
130
131
132
133
134
135
136
# File 'lib/active_enum/extensions.rb', line 126

def define_active_enum_question_method(attribute)
  class_eval <<-DEF
    def #{attribute}?(arg=nil)
      if arg
        self.#{attribute}(:id).present? && self.#{attribute}(:id) == self.class.active_enum_for(:#{attribute})[arg]
      else
        super()
      end
    end
  DEF
end

#define_active_enum_read_method(attribute) ⇒ Object

Define read method to allow an argument for the enum component

Examples:

user.sex
user.sex(:id)
user.sex(:name)
user.sex(:enum)
user.sex(:meta_key)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/active_enum/extensions.rb', line 80

def define_active_enum_read_method(attribute)
  class_eval <<-DEF
    def #{attribute}(arg=nil)
      enum = self.class.active_enum_for(:#{attribute})
      return enum if arg == :enum

      value = super()
      return if value.nil?

      case arg
      when nil
        #{ActiveEnum.use_name_as_value ? 'enum[value]' : 'value' }
      when :id
        value if enum.get(value, raise_on_not_found: false)
      when :name
        enum.get(value, raise_on_not_found: false).dup
      when Symbol
        (enum.meta(value, raise_on_not_found: false) || {})[arg].try(:dup)
      end
    end
  DEF
end

#define_active_enum_write_method(attribute) ⇒ Object

Define write method to also handle enum value

Examples:

user.sex = 1
user.sex = :male


109
110
111
112
113
114
115
116
117
118
119
# File 'lib/active_enum/extensions.rb', line 109

def define_active_enum_write_method(attribute)
  class_eval <<-DEF
    def #{attribute}=(arg)
      if arg.is_a?(Symbol)
        super(self.class.active_enum_for(:#{attribute})[arg])
      else
        super
      end
    end
  DEF
end

#define_implicit_enum_class_for_attribute(attribute, block) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/active_enum/extensions.rb', line 63

def define_implicit_enum_class_for_attribute(attribute, block)
  enum_class_name = "#{name}::#{attribute.to_s.camelize}"
  eval("class #{enum_class_name} < ActiveEnum::Base; end")
  enum = enum_class_name.constantize
  enum.class_eval(&block)
  enum
end

#enumerate(*attributes, &block) ⇒ Object

Declare an attribute to be enumerated by an enum class

Example:

class Person < ActiveRecord::Base
  enumerate :sex, :with => Sex
  enumerate :sex # implies a Sex enum class exists

  # Pass a block to create implicit enum class namespaced by model e.g. Person::Sex
  enumerate :sex do
    value :id => 1, :name => 'Male'
  end

  # Multiple attributes with same enum
  enumerate :to, :from, :with => Sex


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/active_enum/extensions.rb', line 28

def enumerate(*attributes, &block)
  options = attributes.extract_options!
  self.enumerated_attributes ||= {}

  attributes_enum = {}
  attributes.each do |attribute|
    begin
      if block_given?
        enum = define_implicit_enum_class_for_attribute(attribute, block)
      else
        enum = options[:with] || attribute.to_s.camelize.constantize
      end

      attribute = attribute.to_sym
      attributes_enum[attribute] = enum

      define_active_enum_methods_for_attribute(attribute, options) unless options[:skip_accessors]
    rescue NameError => e
      raise e unless e.message =~ /uninitialized constant/
      raise ActiveEnum::EnumNotFound, "Enum class could not be found for attribute '#{attribute}' in class #{self}. Specify the enum class using the :with option."
    end
  end
  enumerated_attributes.merge!(attributes_enum)
end