Multiparameter Attributes Handler

Background

Rails form helpers for time, datetime and date return multiparameter attributes that ActiveRecord objects are able to convert into parent attributes.

For example

date_select(:thing, :last_read)

when set to 24th June 2004, will generate

'thing' => {
     "last_read(1i)" => "2004", 
     "last_read(2i)" => "6", 
     "last_read(3i)" => "24"
}

ActiveRecord understands this and converts these key/value pairs into a date object that is passed to thing.last_read=

A solution without ActiveRecord

Multiparameter Attributes Handler allows other objects to do the same.

thing_params = MultiparameterAttributesHandler.manipulate_all(params[:thing])

This creates a last_read key with a time object derived from the values

thing_params == {
    "last_read(1i)" => "2004", 
    "last_read(2i)" => "6", 
    "last_read(3i)" => "24",
    "last_read"     => Time.local('2004', '6', '24')
}

So for a ActiveResource Thing, this functionality can be added by over-riding the attributes setter:

class Thing < ActiveResource::Base
  def attributes=(params)
    super MultiparameterAttributesHandler.manipulate_all(params)
  end
end

However, as the params splitting and rebuilding is happening in the views and controller space, it might well make more sense to do the manipulation in the controller:

class ThingsController < ApplicationController

  ....

  def update
    @thing = Thing.find(params[:id])
    @property.update_attributes thing_params
    redirect_to @property
  end

  private
  def thing_params
    MultiparameterAttributesHandler.manipulate_all(params[:thing])
  end
end

Only setter affected

Note that this gem provides handling of the parameters received from the form submission. For the form helpers to work, they need to passed a date or time to the form.

One solution is to override the getter in the model. So for the Thing example above:

require 'date'
class Thing < ActiveResource::Base

  def last_read
    Time.parse(super)
  end
end

Rails form date helpers will then work for last_read:

datetime_select(:thing, :last_read)

Installation

This functionality is made available via the multiparameter_attributes_handler gem. So add this to your gemfile:

gem 'multiparameter_attributes_handler'