Module: MongoMapper::Plugins::MultiParameterAttributes::InstanceMethods

Defined in:
lib/mm-multi-parameter-attributes.rb

Instance Method Summary collapse

Instance Method Details

#assign_multiparameter_attributes(pairs) ⇒ Object

Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done by calling new on the column type or aggregation type (through composed_of) object with these parameters. So having the pairs written_on(1) = “2004”, written_on(2) = “6”, written_on(3) = “24”, will instantiate written_on (a date type) with Date.new(“2004”, “6”, “24”). You can also specify a typecast character in the parentheses to have the parameters typecasted before they’re used in the constructor. Use i for Fixnum, f for Float, s for String, and a for Array. If all the values for a given attribute are empty, the attribute will be set to nil.



34
35
36
37
38
# File 'lib/mm-multi-parameter-attributes.rb', line 34

def assign_multiparameter_attributes(pairs)
  execute_callstack_for_multiparameter_attributes(
    extract_callstack_for_multiparameter_attributes(pairs)
  )
end

#attributes=(new_attributes) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/mm-multi-parameter-attributes.rb', line 9

def attributes=(new_attributes)
  return if new_attributes.nil?

  multi_parameter_attributes = []
  normal_attributes = {}

  new_attributes.each do |k, v|
    if k.to_s.include?("(")
      multi_parameter_attributes << [ k.to_s, v ]
    else
      normal_attributes[k] = v
    end
  end

  assign_multiparameter_attributes(multi_parameter_attributes)

  super(normal_attributes)
end

#execute_callstack_for_multiparameter_attributes(callstack) ⇒ Object



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
# File 'lib/mm-multi-parameter-attributes.rb', line 40

def execute_callstack_for_multiparameter_attributes(callstack)
  callstack.each do |name, values_with_empty_parameters|
    # in order to allow a date to be set without a year, we must keep the empty values.
    # Otherwise, we wouldn't be able to distinguish it from a date with an empty day.
    values = values_with_empty_parameters.reject(&:nil?)

    if !values.reject{|x| x.blank? }.empty?
      values = values.map(&:to_i)

      key = self.class.keys[name]
      raise ArgumentError, "Unknown key #{name}" if key.nil?
      klass = key.type

      value = if Time == klass
        Time.zone.local(*values)
      elsif Date == klass
        begin
          values = values_with_empty_parameters.map{|v| v.blank? ? 1 : v.to_i}
          Date.new(*values)
        rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
          Time.zone.local(*values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
        end
      else
        klass.new(*values)
      end
      writer_method = "#{name}="
      if respond_to?(writer_method)
        self.send(writer_method, value)
      else
        self[name.to_s] = value
      end
    end
  end
end

#extract_callstack_for_multiparameter_attributes(pairs) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/mm-multi-parameter-attributes.rb', line 75

def extract_callstack_for_multiparameter_attributes(pairs)
  attributes = { }

  for pair in pairs
    multiparameter_name, value = pair
    attribute_name = multiparameter_name.split("(").first
    attributes[attribute_name] = [] unless attributes.include?(attribute_name)

    attributes[attribute_name] << [ find_parameter_position(multiparameter_name), value ]
  end

  attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
end

#find_parameter_position(multiparameter_name) ⇒ Object



89
90
91
# File 'lib/mm-multi-parameter-attributes.rb', line 89

def find_parameter_position(multiparameter_name)
  multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
end