FreeCamp      

【Rails】Gem cocoonを用いて親子孫関係の構築

前回は親子関係で同時にフォームの内容を保存してみました。
今回は親・子・孫といった三つのモデルのレコードを同時に保存していきたいと思います。

目次

  1. Gem cocoonを用いて親子関係のアプリケーションを作成
  2. 親子孫のフォームを作成
    1. 孫モデルを作成
    2. コントローラの編集
    3. フォームの作成
  3. 完成コード

1. Gem cocoonを用いて親子関係のアプリケーション作成

まずはじめに、親子関係のみのアプリケーションを作成しましょう。
それぞれのモデル名は以下の通りです。

モデル名カラム名データ型
Parentnamestring
Childnamestring
parent_idinteger
Grandchildnamestring
child_idinteger

それでは下記記事を参考に親子関係のアプリケーションを作成していきます。

$ 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は制約が厳しいですが、規則通りに作成すれば便利になると思います。
ぜひ一度お試しを。

3. 完成ソースコード

https://github.com/ssshhhooota/rails_cocoon2