Module: EnumeratedField::ClassMethods

Defined in:
lib/enumerated_field.rb

Instance Method Summary collapse

Instance Method Details

#enum_field(field_name, values_array, options = {}) ⇒ Object

ex. enum_field(:league, [[‘National Football League’, :nfl], [‘Major League Baseball’, :mlb]]) field_name typically corresponds to the database column name values_array is a double array (not a hash to preserve order for when order matters.. ie select options)



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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/enumerated_field.rb', line 15

def enum_field(field_name, values_array, options = {})
  values_hash = ActiveSupport::HashWithIndifferentAccess.new
  values_array.each { |value, key| values_hash[key] = value }
  default_options = {
    :validate => true,
    :allow_nil => false,
    :allow_blank => false,
  }
  options = default_options.merge(options)

  # returns the values_array for this field, useful for providing to
  # options_for_select when constructing forms
  enumerated_class = class << self; self; end
  enumerated_class.class_eval do
    define_method("#{field_name}_values") do |*options|
      options = options.first || {}
      if options[:first_option]
        [[options[:first_option], '']] + values_array
      else
        values_array
      end
    end
  end

  class_eval do

    unless options[:validate] == false
      valid_values = values_hash.keys
      values_hash.keys.map do |key|
        if key.is_a?(String) and not key.blank?
          valid_values << key.to_sym
        else
          valid_values << key.to_s
        end
      end
      validates field_name, :inclusion => valid_values,
        :allow_nil => options[:allow_nil], :allow_blank => options[:allow_blank]
    end

    values_hash.each do |key, value|
      const_name = "#{field_name}_#{key}".upcase.gsub(/[^\w_]/, "_").to_sym
      const_set(const_name, key)
    end

    define_method("#{field_name}_values") do |*options|
      self.class.send("#{field_name}_values", *options)
    end

    # returns display value for the current value of the field
    define_method("#{field_name}_display") do
      values_hash[send(field_name)]
    end

    # returns display value for the given value of the field
    define_method("#{field_name}_display_for") do |key|
      values_hash[key]
    end

    define_method("#{field_name}_value_for") do |key|
      values_hash.invert[key]
    end

    # defines question methods for each possible value of the field
    # ex.  object.league_nfl?  which returns true if the objects league 
    # field is currently set to nfl otherwise false
    values_hash.keys.each do |key|
      define_method("#{field_name}_#{key}?") { send(field_name).to_s == key.to_s }
    end

    if defined? ActiveRecord::Base and ancestors.include? ActiveRecord::Base
      values_hash.keys.each do |key|
        scope "#{field_name}_#{key}", where(field_name => key)
      end
    end

  end
end