① _attributes
とaccepts_nested_attributes_for
accepts_nested_attributes_for
メソッドを親モデルに追加することで、親モデルの作成や更新時に、関連する子モデルも同時に作成や更新することができる。
一方、_attributes
はストロングパラメータ内で使用され、親モデルとともに子モデルの属性を許可するために使用される。
したがって、親モデルと子モデルの関連を扱い、同時に子モデルの属性を作成や更新したい場合、_attributes
とaccepts_nested_attributes_for
メソッドをセットで使用するのが一般的。
② dependent: :destroy
オプション
has_manyの関連付けに加えて使用するオプション。
親オブジェクトが削除されると、関連する子オブジェクトも自動的に削除されるようになる。
関連付けをしているにも関わらず、このオプションを付けずに親の削除をしようとするとエラーになる。
③ allow_destroy: true
オプション
accepts_nested_attributes_for
に加えて使用するオプション。
(②のdependent: :destroy
は親レコードが削除されたときに、自動的に子レコードも削除するオプション。
しかし、このオプションでは親レコードと子レコードを個別に編集・削除する場合には対応できない。親レコードが削除された場合のみ、子レコードも削除されることになる。)
一方で、allow_destroy: true
は、親レコードを更新する際に、子レコードを編集・削除することができるオプション。
親レコードが削除されることなく、子レコードを編集・削除することが可能になる。
(例えば、親レコードを更新する際に、子レコードを追加・削除・変更することができる。)
結論
総括すると、has_many :barcodetags
だけでも関連付けの意味があるが、親モデルのフォームから子モデルの属性を同時に扱う場合には、_attributes
とaccepts_nested_attributes_for
メソッドも使用する必要がある。
また、場合によっては、allow_destroy: true
を使用して、子要素のみの編集・削除も可能にする必要がある。
コード例
親モデルのコントローラー(tagsテーブルのnameカラムに書き込みできるように処理を追加)
def recipe_params
params.require(:recipe).permit(:title, :content, :time, :price, :calorie, :image,
tags_attributes: [:name])
end
子モデル
class Recipe < ApplicationRecord
belongs_to :user
has_many :tags, dependent: :destroy
accepts_nested_attributes_for :tags, allow_destroy: true
end