What Does ActiveRecord::MultiparameterAssignmentErrors Mean?

后端 未结 7 632
[愿得一人]
[愿得一人] 2020-12-15 22:46

I have a rails form with a datetime_select field. When I try to submit the form, I get the following exception:

ActiveRecord::MultiparameterAssignmentErrors          


        
相关标签:
7条回答
  • 2020-12-15 23:12

    ActiveRecord throws the MultiparameterAssignmentErrors exception when you try to set an invalid date to a models attribute.

    Try to pick a Nov 31 date from the date_select or datetime_select dropdown and you will get this error.

    0 讨论(0)
  • 2020-12-15 23:13

    This error can also occur with webrat/cucumber when filling in form data using a table.

    eg this doesn't work:

    When I fill in the following:
      | report_from_1i | 2010     |
      | report_from_2i | January  |
      | report_from_3i | 1        |
      | report_to_1i   | 2010     |
      | report_to_2i   | February |
      | report_to_3i   | 1        |
    

    but this does:

    When I fill in the following:
      | report_from_1i | 2010 |
      | report_from_2i | 1    |
      | report_from_3i | 1    |
      | report_to_1i   | 2010 |
      | report_to_2i   | 2    |
      | report_to_3i   | 1    |
    
    0 讨论(0)
  • 2020-12-15 23:16

    It turns out that rails uses something called Multi-parameter assignment to transmit dates and times in small parts that are reassembled when you assign params to the model instance.

    My problem was that I was using a datetime_select form field for a date model field. It apparently chokes when the multi-parameter magic tries to set the time on a Date object.

    The solution was to use a date_select form field rather than a datetime_select.

    0 讨论(0)
  • 2020-12-15 23:19

    Super hack, but I needed to solve this problem right away for a client project. It's still a bug with Rails 2.3.5.

    Using either date_select or datetime_select, if you add this to your model in the initialize method, you can pre-parse the passed form-serialized attributes to make it work:

    def initialize(attributes={})
      date_hack(attributes, "deliver_date")
      super(attributes)
    end
    
    def date_hack(attributes, property)
      keys, values = [], []
      attributes.each_key {|k| keys << k if k =~ /#{property}/ }.sort
      keys.each { |k| values << attributes[k]; attributes.delete(k); }
      attributes[property] = values.join("-")
    end
    

    I am using this with a nested, polymorphic, model. Here's a question I had showing the models I'm using. So I needed accepts_nested_attributes_for with a datetime.

    Here's the input and output using the console:

    e = Event.last
    => #<Event id: 1052158304 ...>
    e.model_surveys
    => []
    e.model_surveys_attributes = [{"survey_id"=>"864743981", "deliver_date(1i)"=>"2010", "deliver_date(2i)"=>"2", "deliver_date(3i)"=>"11"}]
    PRE ATTRIBUTES: {"survey_id"=>"864743981", "deliver_date(1i)"=>"2010", "deliver_date(2i)"=>"2", "deliver_date(3i)"=>"11"}
    # run date_hack
    POST ATTRIBUTES: {"survey_id"=>"864743981", "deliver_date"=>"2010-2-11"}
    e.model_surveys
    => [#<ModelSurvey id: 121, ..., deliver_date: "2010-02-11 05:00:00">]
    >> e.model_surveys.last.deliver_date.class
    => ActiveSupport::TimeWithZone
    

    Otherwise it was either null, or it would throw the error:

    1 error(s) on assignment of multiparameter attributes

    Hope that helps, Lance

    0 讨论(0)
  • 2020-12-15 23:27

    This is not a bug in Rails, it is the intended behavior of the multi-parameter attribute writer. I'm willing to bet that the original poster's deliver_date field in the database is a varchar as opposed to a date or datetime type. ActiveRecord uses each part of the multi-parameter attribute to send to the new method of the serialized type. The number 1, 2, 3, etc indicates the constructor parameter position and the "i" tells ActiveRecord to call to_i on the parameter before passing it to the constructor. In this case they are all "i's" because DateTime.new(year, month, day) expects three Integers not three Strings.

    If the deliver_date column in the database isn't a type that's serialized to a DateTime then ActiveRecord will throw a ActiveRecord::MultiparameterAssignmentErrors exception because String.new(2010,2,11) won't be successful.

    Source: https://github.com/rails/rails/blob/v3.0.4/activerecord/lib/active_record/base.rb#L1739

    0 讨论(0)
  • 2020-12-15 23:38

    Like Zubin I've seen this exception when the form submits a month as a month name rather than a numerical month string (eg. October rather than 10).

    One user agent I've encountered seems to submit the contents of the option tag rather than the value attribute:

    Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE66-1/300.21.012; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413

    So in the case of submitting a multi-parameter date from a helper generated select (from date_select helper) your params will have:

    "event"=> {
        "start_on(2i)"=>"October",
        "start_on(3i)"=>"19",
        "start_on(1i)"=>"2010"
    }
    

    This creates an exception: ActiveRecord::MultiparameterAssignmentErrors: 1 error(s) on assignment of multiparameter attributes

    Most user agents will correctly submit:

    "event"=> {
        "start_on(2i)"=>"10",
        "start_on(3i)"=>"19",
        "start_on(1i)"=>"2010"
    }
    
    0 讨论(0)
提交回复
热议问题