複数の関連を跨いでaccepts_nested_attributes_forを使う場合の話。
たとえば
Organization has_many Groups Group has_many Employees
というモデルに対して、1度にまとめてこれらのレコードを作成したい場合には次のようにする。
まずはクラスの定義:
class Organization has_many :groups, inverse_of: :organization accepts_nested_attributes_for :groups # attributes: # name:string end class Group belongs_to :organization, inverse_of: :groups has_many :employees, inverse_of: :group accepts_nested_attributes_for :employees validates :organization, presence: true # attributes: # name:string end class Employee belongs_to :group, inverse_of: :employees validates :group, presence: true # attributes: # name:string end
:inverse_of
オプションで親から自分を参照するときの関連名を指定する必要があるっぽい。これを指定していなかったら、バリデーション時にすでに作成されていたであろう親(EmployeeからGroup)を参照できなくてエラーが出た。
レコードを作成するには次のようなハッシュ構造を渡す:
Organization.create!({ name: "組織名", groups_attributes: [ { name: "グループ名", employees_attributes: [ { name: "人名" } ] } ] })
関連先の属性は#{関連名}_attributes
というキーにハッシュの配列で渡す*1。
これをstrong_parametersで使うには次のように指定する:
params.require(:organization).permit( :name, { groups_attributes: [ :name, { employees_attributes: [ :name ] } ] } )
createだけならこれでいいけど、もしupdateも行う場合にはxxx_attributesに:id
も含める。
フォームはfields_forで次のような感じ:
(あとで書く)
*1:has_oneの場合にはハッシュをそのまま渡す