Cocoonで親子（孫）関係で、動的にフォームを追加削除する

## 前提
親(Project)-子(task)-孫(item) 関係
子を消すと孫も消える

## 環境
rails 5.1.5

#　Cocoonのインストール
gem入れてjavascript.rbにcocoonの呼び出し文追加
（ここあとで加筆）

##　設定
### model
```ruby:project.rb
class Project < ApplicationRecord
  has_many :tasks, inverse_of: :project
  accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
end
```
```ruby:task.rb
class Task < ApplicationRecord
  belongs_to :project
  has_many :items, inverse_of: :task
  accepts_nested_attributes_for :items, reject_if: :all_blank, allow_destroy: true
end
```
```ruby:item.rb
class Item < ApplicationRecord
  belongs_to :task
end
```
- allow_destroy: true　としていないと子項目の削除ができない

### controller
```ruby:projects_controller.rb
  def new
    @project = Project.new
    @task = @project.tasks.build
    @item = @task.items.build
  end

  :

private
    def project_params
    params.require(:project).permit(:name, :description, tasks_attributes: [:id, :description, :done, :_destroy,
                                                         items_attributes: [:id, :description, :_destroy]])
    end
```
- 合わせてストロングパラメーターの _destroy も入れておく必要がある（入れないと削除できない）
- 子要素は親要素のストロングパラメーターに含めて記述できる
- インスタンスは最初に表示した時のフォームに対応するので、子用のフォームが最初になくても良ければ`@project = Project.new`だけでよさそう
 
### View
```erb:new.html.erb
<h1>New Project</h1>
<%= render 'form', project: @project %>
<%= link_to 'Back', projects_path %>
```
```erb:_form.html.erb
<%= form_for @project do |f| %>
  <div class="field">
    <%= f.label :name, "name" %>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description, "description" %>
    <%= f.text_field :description %>
  </div>
  <h3>Tasks</h3>
  <div id="tasks">
    <%= f.fields_for :tasks do |task| %>
      <%= render 'task_fields', f: task %>
    <% end %>
    <div id="links">

      <%= link_to_add_association 'add task',f, :tasks %>
    </div>
    <%= f.submit %>
  </div>
<% end %>
```
```erb:_task_fields.html.erb
<div class="nested-fields well well-compact">
  <div class="form-group">
    <%= f.label :description %>
    <%= f.number_field :description %><br>
    <%= link_to_remove_association "remove task", f %>
  </div>

  <div class="items">
    <%= f.fields_for :items do |item| %>
      <%= render 'item_fields', f: item %>
    <%end%>
    <div class="links">
      <%= link_to_add_association "add item", f, :items %>
    </div>
  </div>
</div>

```
```erb:_item_fields.html.erb
<div class="nested-fields form-inline">
  <div class="form-group">
    <%= f.label :itemdescription %>
    <%= f.number_field :description %>
  </div>
</div>
```
-  _{model}_fields.html.erbというパーシャル名が固定（拡張子はいくつかフォローされてるので要公式確認）
- 上記パーシャルへnested-fieldsというclassを設定する
- =link_to_add_attributesの前にlinksというclassを設定する


### ハマリポイント：
rails5からはjQueryのサポートがないので、gemのインストールが必要
`gem "jquery-rails"`

以下の追記も必要

```js:application.js
//= require jquery
```

それでも動かない場合、Appication.jsへの”述の順番見るといいかも
//= require jquery　←
//= require rails-ujs
//= require turbolinks
//= require_tree .
//= require cocoon　←

cocoonはjqueryを前提にしているので、先に記述がないとだめみたい
エラーになった順番大事…

#### 感想
- 公式が上げてるデモサンプルコード見て実装するのいいかも…！（その通りにやったらできた）https://github.com/nathanvda/cocoon_simple_form_demo

- フォームパーシャルで切ってると、editとnewを全然いじらなくていいのでめっちゃ楽
- サンプルコードがhtm.erbじゃなくてhamlという書式？を使っていたので読解に手間取った

####　参考
cocoonをRails5.1で使用しようと思った時にハマる罠
http://toyokappa.hatenablog.com/entry/2017/09/15/001537

【jQuery】プログラム動かない時に確認すること
http://mikaduki.info/webprogram/js/jquery/1192/


cocoon を使って、ネストしたフォームを作る
http://mikazuki.hatenablog.jp/entry/2016/03/26/040229

マークアッパー的 Haml入門21の手引き
http://fukuyama.co/haml2

Hamlでクラスを複数指定する。
https://qiita.com/s_osa/items/82afd6e543fe4298a2d8