cocoonをRails5.1で使用しようと思った時にハマる罠
最近新しいアプリケーションの開発を進めています。このアプリケーションを作成するにあたり「Gemがあればとにかく使って実装」という方針で進めています。Knowledge Stockerを実装する際はどちらかと言うと「自分で書いて実装してみる」という流れで作っていたので、Gemに慣れるという密かな目的を推進しています。
そんな中、accepts_nested_attributes_for
を使いネストしたフォームを作る際に、フォームを非同期的に追加、削除するという動作が必要となったためcocoon
というGemを使ってみました。そこでハマった内容を備忘録的な感じにまとめてみました。
cocoonとは
先程触れたように、ネストしたフォームを非同期的に追加、削除を行うためのGemです。色々と調べてみると、これまではnested_form
を使って実装をすることが流行っていたようなのですが、Gemのアップデートが4、5年前から止まっており、cocoon
に乗り換える方々も多い模様。直近サポートされていないGemよりもサポートされているGemの方が安心だろうということでcocoon
を使ってみることにしました。
使ってみた
英語が読めないながらも必死にREADMEを見ながら設定をしていきました。設定方法は意外とシンプルで
- Gemをインストール
application.js
を設定- ModelやControllerを設定
cocoon
の書き方に従ったフォームの作成
をするだけとのこと。(念のため手順は下記に記載します)
環境
Gemのインストール
Gemfile
にcocoon
を追加しbundle install
。
gem "cocoon"
$ bundle install
application.jsの設定
application.js
に下記の一文を追加。
//= require cocoon
Modelの設定
Modelを下記のとおりに設定する。
class Plan < ActiveRecord::Base has_many :locations, inverse_of: :plan accepts_nested_attributes_for :locations, reject_if: :all_blank, allow_destroy: true end class Location < ActiveRecord::Base belongs_to :plan end
Controllerの設定
ControllerのStrong Parametersを下記の通り設定する。
def plan_params params.require(:plan).permit(:name, :description, locations_attributes: [:id, :name, :description, :_destroy]) end
フォームを作成
cocoon
の仕様に従い下記の通りフォームを作成します。
app/views/plans/_form.html.slim
= form_with model: @plan, local: true do |f| - if @plan.errors.any? ul.error-explanation - @plan.errors.full_messages.each do |message| li= message .form-group = f.label :name = f.text_field :name, class: "form-control" .form-group = f.label :description = f.text_area :description, class: "form-control" h2 = t("view.spot_registration") = f.fields_for :locations do |location| = render "location_fields", f: location .links = link_to_add_association f, :locations, class: "btn btn-primary btn-add" = f.submit class: "btn btn-primary"
app/views/plans/_location_fields.html.slim
.nested-fields .form-group = f.label :name = f.text_field :name, class: "form-control" .form-group = f.label :description = f.text_area :description, class: "form-control" = link_to_remove_association f, class: "btn btn-danger btn-remove"
この時に必ず用意しなければならないのは下記の3つのようです。
_{model}_fields.html.slim
というパーシャル- 上記パーシャルへ
nested-fields
というclass
を設定する =link_to_add_attributes
の前にlinks
というclass
を設定する
cocoon × Rails 5.1の罠
さて上記の設定が完了したので、実際に動くかどうか試してみよう!と思いフォームの追加ボタン、削除ボタンをポチッとな!
ポチッ!ポチ!ポチ!ポチ!
無反応・・・
そうなんです。このままでは動かないのです。この罠にハマりました。Javascriptが動いていないはなんとなくわかったのですが、何故動かないのかが、分からず色々と調べてみました。するとRails 5.1からjQeryをサポートしていないという情報に行き着くことに。そしてcocoon
はjQueryを前提に作られているというのをREADMEで見たような・・・!!
そうなんです。cocoon
はjQueryを使っているのでRails 5.1の標準の状態では動かないのです。という訳でRails 5.1でjQueryが動くように設定をしてあげました。
jQueryの設定
Rails 5.1でjQueryを動かすにはjquery-rails
というGemをインストールしてあげます。
gem "jquery-rails"
そしてapplication.js
に下記を追加します。
//= require jquery
これで準備完了!そしてフォームの追加ボタン、削除ボタンを押してみると、、、見事動きました!ということで、無事、cocoon
を導入することが出来ました。
しかしながら、今後RailsがjQueryをサポートしないことを考えるとcocoon
を導入する事自体も考えなければならなそうですね。以上、色々と勉強になった1日でした。