MultiParameterAssignmentErrorsは複数の属性でエラーが発生した際に出力される

[API dock](https://apidock.com/rails/ActiveRecord/MultiparameterAssignmentErrors)や[公式Github](https://github.com/rails/rails/blob/main/activerecord/lib/active_record/errors.rb#L364)に書いてあることそのままのタイトル

Rails6.1.4にて検証

---

# 経緯
対象となるModelは以下の通り

```rb
class TestModel < ActiveRecord::Base
  validates_datetime :column_datetime
  validates_date :column_date
end
```

RSpecのエラー調査をしている時にこんなソースを見た

```rb
it "short params is nil" do
  expect(TestModel.new("column_date(1i)" => "2021", "column_date(2i)" => "13").\
  to raise_error(ActiveRecord::MultiParameterAssignmentErrors)
end
```

テスト名で`nil`として返ってくることを想定しているのに例外処理書いているのはさておき、
この`MultiParameterAssignmentErrors`を当方見たことがなかったのでどういった時に出されるのかを調べてみた

# 調査

困ったときのAPI dock

> Raised when there are multiple errors while doing a mass assignment through the {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method. The exception has an errors property that contains an array of AttributeAssignmentError objects, each corresponding to the error while assigning to an attribute.

要するに`attributes=`による属性更新中に複数のエラーが発生した場合にこのエラーが出力されるとのこと
そのような状況は今までに何度も遭遇したのに見たことがないのはなぜ...？

実際に下記のような操作を行ってみたが確認できず

```rb
create_table(:users) do |t|
  t.string :name
  t.integer :age
end

User.new(name: 19, age: "name")
# => User(name: "19", age: 0)
```

以前、[attributesは自動的にタイプキャストする仕様だと特定した](https://qiita.com/arukuishi/items/d5d4e216fcbfde7b1720)ことをすっかり忘れていた

このエラーが記載してあった箇所はDate等の時刻系であったことを思い出し、再度試してみる

```rb
TestModel.new("column_date(1i)" => "9999", "column_date(2i)" => "9999"
# => nil
```

どうも上手くいかない
行き詰ったため公式Githubのソースを読んでいたところ、このような記述を発見

```rb:rails/activerecord/lib/active_record/attribute_assignment.rb
      def execute_callstack_for_multiparameter_attributes(callstack)
        errors = []
        callstack.each do |name, values_with_empty_parameters|
          if values_with_empty_parameters.each_value.all?(NilClass)
            values = nil
          else
            values = values_with_empty_parameters
          end
          send("#{name}=", values)
        rescue => ex
          errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
        end
        unless errors.empty?
          error_descriptions = errors.map(&:message).join(",")
          raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
        end
      end
```

これで調べてみると[かなり類似する内容の記事を発見](https://qiita.com/snaka/items/46938110af0cab6c4ecd)

`assign_attributes`でタイプキャストされた後に`values_with_empty_parameters.each_value.all?(NilClass)`で`nil`か否かを判別する、このタイミングでエラーを発生させないと`MultiParameterAssignmentErrors`は出力されなさそう

## つまり？

タイプキャスト後にnilにならず例外的な処理になるような値を登録する必要があるらしい

そう考えると時刻系でよく発生するエラーであることが良くわかる

```rb
※見やすいように改行しています

TestModel.new("column_date(1i)" => "9999", "column_datetime(1i)" => "9999"
# => ActiveRecord::MultiparameterAssignmentErrors: 1 error(s) 
#    on assignment of multiparameter attributes [error on
#    assignment [0] to column_datetime (Provided hash {1=>0} 
#    doesn't contain neccessary keys: [2, 3])]
```

やっと確認できた