attr_accessor for a date and problems using select_date

2.3k Views Asked by At

I'm trying to use attr_accessor for a date which normally works fine except when I attempt to use it with the select_date helper method.

Looking at the code behind the helper method I'm guessing it looks for the table column with date type. And in this case since there is no table it's not handling it correctly and I get:

ActiveRecord::MultiparameterAssignmentErrors

"search"=>{"number_of_days"=>"3",
 "searchable_id"=>"6933",
 "startdate(1i)"=>"2011",
 "startdate(2i)"=>"2",
 "startdate(3i)"=>"11"}}

Is there a way around this? Or do I need to create some kind of before filter in the controller? I'd prefer doing it on the model level, but I'm not sure how to handle this case? An attr_accessor for each seems a bit over kill. Anyone else have an elegant solution?

4

There are 4 best solutions below

1
On

attr_accessor fields don't usually get saved when you save/update to the model. How are you updating the model?

Also, you can convert the startdate params to a date object like this :

@start_date = Date.civil(params[:search][:"startdate(1i)"].to_i,params[:search][:"startdate(2i)"].to_i,params[:search][:"startdate(3i)"].to_i)

Check here

0
On

select_date is for building the dropdowns which are not associated with a model field (with the idea that you can then pick them up on the other side and do what you want with them). I assume you're meaning date_select which does run off the model?

In any case, as far as I know, long story short, there's no nice and pretty way to get this to work. It's not because of the way the helper works, but because of the way that active record deals with these attributes split into multiple parameters.

In a bit more detail if you're interested, the reason why this doesn't work easily is because when Active Record is dealing with the params you've passed in, it goes through execute_callstack_for_multiparameter_attributes which interprets the keys which have been split into the "date(1i)" style, and mungs them into the applicable class which they should be (a date or time object). The way it works out whether it should create a date or time is by checking it against the type of the attribute (see here), but since an your 'startdate' attribute isn't bound to a particular type, it doesn't get treated as a date or datetime column in the db would.

I think I would deal with it similarly to @Phyo-Wai-Win, but use select_date to set a different param, outside of the 'search' namespace which you then pass into the model as appropriate in the controller. This way, it's not much work, and it means you're not messing with the way you initialize the record or what attributes it expects.

0
On

Coming in way late, but in case anyone else stumbles by, the answer for modern rails lies in include ActiveRecord::AttributeAssignment in your model.

This answer did it for me.

0
On

I'm a little late here, but I just came across this problem and did not like the top answer. I found a method in the ActiveRecord source called extract_callstack_for_multiparameter_attributes (this is different than the method idlefingers mentioned)

I have the following method in my model. I am calling this method manually but you could probably override update_attributes to run it automatically when you save from the controller. The params argument is actually params[:my_model] from the controller.

attr_accessor :submit_from, :submit_to

def set_dates(params)
  dates = extract_callstack_for_multiparameter_attributes(params)

  dates.each_pair do |field, date_array|
    send "#{field}=", Date.new(*date_array)
  end
end