コレクションを含むフォームを作る際の注意点

【自分が躓いたので忘れぬようメモ】

コレクションのフォームエレメントをヘルパーで生成する際モデル名にあたる部分に[]を付ける。

text_field("model_name[]", "column_name")

すると以下のHTMLが生成される。

# コレクションのインスタンスがnew_record? == trueの場合
<input id="model_name__column_name" name="model_name[][column_name]" type="text">

# コレクションのインスタンスがnew_record? == falseの場合
<input id="model_name_1_column_name" name="model_name[1][column_name]" type="text">

コレクションのインスタンスがモデルに保存されているか否かにより若干生成されるHTMLが異なり
保存されている場合はid属性とname属性にその行のidが付与される。上記の例では1が付与されていることが
わかる。

ここからが本題

上記のようにフォームエレメントの中にnew_record? == trueのものとnew_record? == falseのものを含むフォームを送信するとInternal Server Errorとなる
ログを見ると下記のエラーが記録されている


Status: 500 Internal Server Error
Conflicting types for parameter containers.
Expected an instance of Array but found an instance of Hash.
This can be caused by colliding Array and Hash parameters
like qs[]=value&qs[key]=value.

エラーメッセージによるとArrayとHashのパラメータが衝突してますよとのこと。
model_name[][column_name]はArray, model_name[1][column_name]はHashと扱われ衝突しているようだ。

よってこの回避策としては以下(など)が考えらる。


1 Array, Hashのどちらかに統一する。
2 model_nameの部分を未登録・既登録によって変える。

ちなみに私の場合2で対処したが、私が知らないだけでRailsは上記のようなケースを想定していてもっとスマートなやり方を
提供しているのかも知れない・・・のでもしご存知でしたら教えてください!