概要
1対多のテーブル構造において、小テーブルのフォームを複数作成するためのGem。
また、公式には、「このgemはjQueryに依存しているので、すでにjQueryを使用しているRailsプロジェクトで最も有効」とあるが、脱jQueryを実施しているプロジェクトではVanilla JS版もある。
今回は脱jQueryで実装する。
導入が違うだけで実装方法はごく普通のcocoon。
テーブル設計
投稿(post)が1に対してジャンル(genre)が多
導入手順
まずはGemfileに追加。
gem 'cocoon'
CDNにて導入。
私はimportmap採用でnode.js/yarnを極力排除したので、CDNにて導入。
(他に何かいい方法があれば教えてください)
<script src='https://unpkg.com/@oddcamp/cocoon-vanilla-js'></script>
or
<%= javascript_include_tag 'https://cdn.jsdelivr.net/npm/@oddcamp/cocoon-vanilla-js@1.1.3/index.min.js' %>
ちなみに公式だと
yarn add @oddcamp/cocoon-vanilla-js
が推奨されている。
model
Post
class Post < ApplicationRecord
has_many :genres, dependent: :destroy
accepts_nested_attributes_for :genres, allow_destroy: true
end
Genre
class Genre < ApplicationRecord
belongs_to :post
end
accepts_nested_attributes_for
accepts_nested_attributes_forを使用することで、指定したモデルのデータを配列としてパラメーターに含めることができる。
引用元
controller
子モデルも作成してあげること、子モデルもパラメーターとして受け取ってあげること。
class PostsController < ApplicationController
def new
@post = Post.new
//子モデルも作成してあげる
@post.genres.build
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to
else
render :new
end
end
private
def recipe_params
params.require(:recipe).permit(:title,
:content,
//子モデルもパラメーターとして受け取ってあげる
genres_attributes: [:name]
)
end
end
view
子モデルのgenreの部分のみ抜粋。
// フォームの追加ボタン
<%= link_to_add_association '追加' %>
// 追加ボタンを押すと、以下が複製されていく
<%= form.fields_for :genres do | genre | %>
<%= genre.file_field :name %>
// フォームの削除ボタン
<%= link_to_remove_association '削除' %>
<% end %>