Gem cocoonを用いて親子孫関係の構築
前回は親子関係で同時にフォームの内容を保存してみました。
今回は親・子・孫といった三つのモデルのレコードを同時に保存していきたいと思います。
目次
- Gem cocoonを用いて親子関係のアプリケーションを作成
- 親子孫のフォームを作成
- 孫モデルを作成
- コントローラの編集
- フォームの作成
- 完成コード
1. Gem cocoonを用いて親子関係のアプリケーション作成
まずはじめに、親子関係のみのアプリケーションを作成しましょう。
それぞれのモデル名は以下の通りです。
モデル名 | カラム名 | データ型 |
Parent | name | string |
Child | name | string |
parent_id | integer | |
Grandchild | name | string |
child_id | integer |
それでは下記記事を参考に親子関係のアプリケーションを作成していきます。
$ rails new rails_cocoon
$ cd rails_cocoon
$ rails g scaffold parent name:string
$ rails db:migrate
cocoonを導入します。
...追加
gem 'cocoon'
gem 'jquery-rails'
$ bundle
...編集
//= require rails-ujs
//= require activestorage
//= require jquery
//= require cocoon
//= require turbolinks
//= require_tree .
Childモデルの作成
$ rails g model Child name:string parent_id:integer
$ rails db:migrate
ParentモデルとChildモデルの関連付け
...追加
has_many :children
accepts_nested_attributes_for :children, allow_destroy: true
allow_destroyは編集を行う時にネストしている子フォームを削除するとレコードを削除してくれます。
逆に指定しないと、子モデルのレコードを削除できません。
...追加
belongs_to :parent
次にフォームを作成していきます。
...編集
def new
@parent = Parent.new
@parent.children.build
end
...編集
def parent_params
params.require(:parent).permit(:name, children_attributes: [:id, :name, :_destroy])
end
@parent.children.buildは@parent.children.newでも大丈夫ですが、
ネストしたフォームを作成する場合は慣習としてbuildを使用します。
次にフォームを編集していきます。
...編集
<div class="children">
<%= form.fields_for :children do |f| %>
<%= f.label "子" %>
<%= render "child_fields", f: f %>
<% end %>
<div class="links">
<%= link_to_add_association "子供を追加", form, :children %>
</div>
</div>
次に部分テンプレートを作成します。
<div class="nested-fields">
<%= f.text_field :name %>
<%= link_to_remove_association "子供を削除", f %>
</div>
ここまでで親子関係の構築は完成しました。
アプリケーションを起動し、試してみましょう。
2. 親子孫のフォームを作成
2.1 孫モデルを作成
$ rails g model Grandchild name:string child_id:integer
$ rails db:migrate
モデルが作成できたら関連付けも行なっていきましょう。
...追加
has_many :grandchildren
accepts_nested_attributes_for :grandchildren, allow_destroy: true
...追加
belongs_to :child
2.2 コントローラの編集
...編集
def new
@parent = Parent.new
@children = @parent.children.build
@children.grandchildren.build
end
2.3 フォームの作成
...編集
<div class="nested-fields">
<%= f.text_field :name %>
<%= link_to_remove_association "子供を削除", f %>
<div class="grandchildren">
<%= f.fields_for :grandchildren do |form| %>
<%= form.label "孫" %>
<%= render "grandchild_fields", f: form %>
<% end %>
<div class="links">
<%= link_to_add_association "孫を追加", f, :grandchildren %>
</div>
</div>
</div>
<div class="nested-fields">
<%= f.text_field :name %>
<%= link_to_remove_association "孫を削除", f %>
</div>
これで完成です。
Cocoonは制約が厳しいですが、規則通りに作成すれば便利になると思います。
ぜひ一度お試しを。