Multi-part parameter extractor
Take the following and place it into your application helper or whatever helper you'd like. To use it you simply pass in an instance of the object on which the multi-part parameter exists. This is so that the type to instantiate can be reflected from the column information. Then you specify the attribute name of the parameter you're looking to create from the next parameter which is the hash containing the multi-part parameter value.
example:
for a form containing dude[birth_date] you'd call the method like this:
extract_date(@the_dude, 'birth_date', params[:dude])
def extract_date(parent_object, param_name, atts)
atts.stringify_keys!
multi_parameter_attributes = []
atts.each do |k, v|
multi_parameter_attributes << [ k, v ] if k.include?(param_name+"(")
end
attributes = { }
for pair in multi_parameter_attributes
multiparameter_name, value = pair
attribute_name = multiparameter_name.split("(").first
attributes[attribute_name] = [] unless attributes.include?(attribute_name)
unless value.empty?
attributes[attribute_name] <<
[ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ]
end
end
attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
errors = []
result = nil
attributes.each do |name, values|
klass = (parent_object.class.reflect_on_aggregation(name.to_sym) || parent_object.column_for_attribute(name)).klass
result = Time == klass ? klass.local(*values) : klass.new(*values)
end
return result
end
def find_parameter_position(multiparameter_name)
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
end
def type_cast_attribute_value(multiparameter_name, value)
multiparameter_name =~ /\([0-9]*([a-z])\)/ ? value.send("to_" + $1) : value
end