Module: AttributeChoices::AttributeChoicesMacro

Defined in:
lib/attribute_choices.rb

Instance Method Summary collapse

Instance Method Details

#attribute_choices(attribute, choices, *args) ⇒ Object

Extends ActiveRecord attributes with a ‘:choices` pseudo-type that provides convenient methods for mapping each choice to its human readable form.

The arguments are:

  • attribute - The attribute whose values you want to map to display values

  • choices - Either an Array of tupples where the first value of the tupple is the attribute \

    value and the second one is the display value mapping, or a +Hash+ where the key is the \
    attribute value and the value is the display value mapping.
    
  • options - An optional hash of options:

    • :localize - If set to true, then I18n.trasnlate is used to translate the value \

      returned by the +_display+ instance methods as well as translate the display \
      values returned by the +_choices+ class method
      
    • :validate - If set to true, validates_inclusion_of is used to ensure that the attribute \

      only accepts the values passed in with the +choices+
      

For example:

class User < ActiveRecord::Base
  attribute_choices :gender,  { 'm' => "Male", 'f' => 'Female'}
  attribute_choices :age_group,  [
    ['18-24', '18 to 24 years old], 
    ['25-45', '25 to 45 years old']
  ], :localize => true, :validate => false
end

The macro adds an instance method named after the attribute, suffixed with _display (e.g. gender_display for :gender) that returns the display value of the attribute for a given value, or nil if a mapping for a value is missing.

It also adds a class method named after the attribute, suffixed with _choices (e.g. User.gender_choices for :gender) that returns an array of choices and values in a fomrat that is suitable for passing directly to the Rails select_* helpers.

NOTE: You can use a Hash for the choices argument which is converted to an Array. The order of the \ tupples of the resulting Array is only guaranteed to be preserved if you are using Ruby 1.9



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
# File 'lib/attribute_choices.rb', line 45

def attribute_choices(attribute, choices, *args)

  assert_valid_attribute(attribute.to_s)

  attribute = attribute.to_sym

  options = args.extract_options!
  options.reverse_merge!(:validate => false, :localize => false)
  options.assert_valid_keys(:validate, :localize)
  
  attribute_choices_options[attribute] = options

  choices = if options[:localize]
    choices.to_a.collect {|t| [t.first, I18n.translate(t.last)]}
  else
    choices.to_a
  end

  define_method("#{attribute.to_s}_display") do
    # The local variable `choices` is saved inside this Proc
    tupple = choices.assoc(send(attribute))
    tupple && tupple.last
  end

  (class << self; self; end).send(:define_method, "#{attribute.to_s}_choices") do
    choices.collect(&:reverse)
  end

  if options[:validate]
    validates_inclusion_of attribute.to_sym, :in => choices.collect {|i| i.first}
  end

end

#attribute_choices_optionsObject

:nodoc:



80
81
82
# File 'lib/attribute_choices.rb', line 80

def attribute_choices_options
  @attribute_choices_options ||= {}
end