概要
cocoonで関連モデルも含めたformを作ることができるが、1対多対1のような、関連先の更に先の関連まで含めたフォームを作るためのTipsがあまりなかった&うまくできない部分もあったので、ここに残しておきます。
cocoonで1対多対1のフォームを作る
コントローラー、ビュー、モデルそれぞれに分けて書いていきます。
モデル
class Parent < ApplicationRecord
has_many :children, dependent: :restrict_with_exception, inverse_of: :parent
accepts_nested_attributes_for :children, allow_destroy: true
end
class Child < ApplicationRecord
belongs_to :parent
has_one :grand_son, dependent: restrict_with_exception, inverse_of: :child
accepts_nested_attributes_for :grand_son, allow_destroy: true
end
class GrandSon < ApplicationRecord
belongs_to :child
end
親側にaccepts_nested_attributes_for
をつければいいだけです。
cocoonのREADMEに書いてあるとおりですね。
コントローラー
class ParentsController < ApplicationController
# 詳細は省略
def create
@parent = Parent.create!(parent_params)
end
private
def parent_params
params.require(:parent).permit(
:name,
children_attributes: [
:id,
:name,
:_destroy,
{
grand_son_attributes: [
:id,
:name,
],
},
])
end
end
以上のような形で、ストロングパラメーターにxxx_attributes
を孫のモデルまで一気に書いてしまいます。
これで一気に孫のモデルまで登録できるようになります。
ビュー
問題はビューです。
このWikiによれば、force_non_association_create
をtrue
にしてしまえば、1個しか追加できないようなのですが、子と孫が1対1の関係の場合は、複数個追加できてしまいます。
これでは狙ったとおりにできないので、自分は以下のように対応しました。
application.js
$('#children')
.on('cocoon:after-insert', function () {
$(this).css('cssText', 'display: none !important');
});
上記のようにすることで、追加ボタンを押した際に、その追加ボタンを消してしまうことができます。
ただ、すごくかっこ悪いので、いい方法があれば、ご教示いいただけますと幸いです。