ネストしたフォームを簡潔に実装できるcocoon gemをwebpack環境でセットアップする

# 前置き

- 公式レポジトリの説明（[nathanvda/cocoon: Dynamic nested forms using jQuery made easy; works with formtastic, simple\_form or default forms](https://github.com/nathanvda/cocoon#rails-31rails-4rails-5)
）には、Rails5までのインストール方法しか説明されていなかった
- Rails6環境でwebpackをつかったインストール方法を知りたかった

## cocoonは、ネストしたフォームをサポートするgem

Railsガイドにも説明のある[ネストしたフォーム](https://railsguides.jp/form_helpers.html#%E3%83%8D%E3%82%B9%E3%83%88%E3%81%97%E3%81%9F%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0)。この実装をサポートしてくれるgemです。

「レシピ」と「手順」が1:Nの関連をもつときに、レシピの登録のとき手順も同時に（複数）作成するときなどに便利です。

```rb:レシピと手順の関連の例
class Recipe < ApplicationRecord
  has_many :steps
end

class Step < ApplicationRecord
  belongs_to :recipe
end
```

このようなフォームをつくれます。

> ![cocoon_form.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/6a0d2831-e9c4-1616-1614-78816b98e95e.gif)



- [【Rails】cocoonを用いて親子孫関係のテーブルに複数のデータを同時保存する方法 \- Qiita](https://qiita.com/hitochan/items/5a45a95e644492d66160)


# 環境

* Ruby (2.7.0)
* Rails (6.0.2.1)
* cocoon (1.2.14)


```rb:Gemfile
gem 'cocoon'
```

## Rails6環境で、`cocoon gem`をつかうための前提知識

以下の点を覚えておく必要があります。

- cocoonは**jQueryに依存**している
- Rails5.1以降はjQueryに依存していないので、**デフォルトでは組み込まれていない**
    - [cocoonをRails5\.1で使用しようと思った時にハマる罠 \- 営業職の俺がエンジニアになる〜群馬Web化計画編〜](http://toyokappa.hatenablog.com/entry/2017/09/15/001537)


# 本題：webpackでcocoonを組み込む方法

## 1. jQueryをセットアップする

- webpackからjQueryを有効にする方法は、[Rails6でjQueryの導入方法 \- Qiita](https://qiita.com/masahisa/items/eaacb0c3b82f4a11fc13)が参考になりました。

## 2. cocoon をセットアップする

以下のスレッドを参考にしました。

- [How to use cocoon gem in Rails 6 \- Stack Overflow](https://stackoverflow.com/questions/57974863/how-to-use-cocoon-gem-in-rails-6?answertab=votes#tab-top)


Gemfileに追加し、`bundle install`します。

```ruby:Gemfile
gem 'cocoon'
```

jQueryとおなじように、`yarn add`で追加していきます。このとき、対象のライブラリ名の指定が特殊になります。（`cocoon`ではなくて`github:nathanvda/cocoon#c24ba53`になります。）

```console
yarn add github:nathanvda/cocoon#c24ba53
```

実行後に、`app/assets/javascripts/cocoon.js`にファイルができているはずです。package.jsonに以下の記述が追加されていればOK。

```json:package.json（追加された行）
"cocoon": "github:nathanvda/cocoon#c24ba53"
```

最後に application.js にimportを追加してください。


```js:app/javascript/packs/application.js
import "cocoon";
```

## よくわかっていないところ
コミット番号については、参照先のスレッドにも

> コミット番号 `#c24ba53` は重要な意味があるので省略してはいけない。

という説明だけでした。このコミットでwebpackに対応した変更が入ったのだとおもわれます。（詳細未調査）

### 2020/02/25 追記：コミット番号の詳細情報

@jnchito さんよりコメントで教えていただきました！


```console
yarn add github:nathanvda/cocoon#c24ba53
```
このコマンドは、[yarn add](https://classic.yarnpkg.com/ja/docs/cli/add/)のリファレンスによると、**「異なる場所からパッケージを指定する」**方法をつかっているようですね。

> yarn add <git remote url>\#<branch/commit/tag>は、指定されたリモートgitリポジトリのgitブランチ、gitコミット、またはgitタグのからパッケージをインストールします。
[yarn add \| Yarn](https://classic.yarnpkg.com/ja/docs/cli/add/)

そのコミットにある、`package.json`を`yarn add`すると、必要なセットアップが完了する仕組みみたいです:+1:

* [Add package\.json with private set to true by dmfrancisco · Pull Request \#454 · nathanvda/cocoon](https://github.com/nathanvda/cocoon/pull/454/commits)

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/600ace55-a1c7-25d7-9080-444f63cc9d3c.png)

### `yarn add cocoon`できるようになる？

上記のコミット日付をみてもらうと`2017/09/14`となっています。
メンテナーの方も**Rails6とあたらしいアセット管理の仕組みを深く理解するまでマージしません**と明記されていました。

提案から2年以上経過しているので、マージされるの？という感じがしています :sweat_smile: 

# おわりに

cocoonの公式レポジトリにあるように、Rails6での使用法は明記されていません（正式対応はもうすこし先？）、ですのでここで説明した方法は今後のアップデートで変更になる場合がありますのでご了承ください。

フロントエンド側のライブラリ（cocoon, jQuery, bootstrapなど）はwebpackに管理させる方法にまだ慣れていなくて、**前の方法で動作しない！**と焦って調べ始めたことが今回の記事のきっかけでした。 :sweat_smile: 

おなじような状況にあったときに、もしかしてwebpackかも？と考える選択肢が増えると解決の糸口がみつかるかもしれませんね！