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])
1 2 def extract_date(parent_object, param_name, atts) 3 atts.stringify_keys! 4 5 multi_parameter_attributes = [] 6 atts.each do |k, v| 7 multi_parameter_attributes << [ k, v ] if k.include?(param_name+"(") 8 end 9 10 attributes = { } 11 12 for pair in multi_parameter_attributes 13 multiparameter_name, value = pair 14 attribute_name = multiparameter_name.split("(").first 15 attributes[attribute_name] = [] unless attributes.include?(attribute_name) 16 17 unless value.empty? 18 attributes[attribute_name] << 19 [ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ] 20 end 21 end 22 23 attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } } 24 errors = [] 25 result = nil 26 attributes.each do |name, values| 27 klass = (parent_object.class.reflect_on_aggregation(name.to_sym) || parent_object.column_for_attribute(name)).klass 28 result = Time == klass ? klass.local(*values) : klass.new(*values) 29 end 30 31 return result 32 end 33 34 def find_parameter_position(multiparameter_name) 35 multiparameter_name.scan(/\(([0-9]*).*\)/).first.first 36 end 37 38 def type_cast_attribute_value(multiparameter_name, value) 39 multiparameter_name =~ /\([0-9]*([a-z])\)/ ? value.send("to_" + $1) : value 40 end