目標
チェックボックスを複数選択し、中間テーブルを介してタグ付け機能を実装する。
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina
E-R図
上記の画像は今回の実装するイメージです。 今回は私が実装したサウナの種類を複数選択して登録する例で話させていただきます。事前準備
画像のようなサウナを新規作成する画面を用意しました。
今回の話で使用するのは、サウナジャンルの複数のチェックボックスを選択して中間テーブルであるサウナジャンルを用いて実装する
方法です。
登録機能など基本的な機能は実装済みの前提でお話させていただきます。
モデルにアソシエーションを記述する
class Sauna < ApplicationRecord
has_many :sauna_genres, dependent: :destroy
has_many :genres, through: :sauna_genres
end
class SaunaGenre < ApplicationRecord
belongs_to :genre
belongs_to :sauna
end
class Genre < ApplicationRecord
has_many :sauna_genres
has_many :saunas, through: :sauna_genres
end
controller
def create
@sauna = Sauna.new(sauna_params)
@sauna.user_id = current_user.id
if @sauna.save
redirect_to user_sauna_path(@sauna)
else
render 'new'
end
end
#省略
def sauna_params
params.require(:sauna).permit(
:name,
genre_ids: []
)
end
genre_ids: []
は複数チェックボックスの値を配列で渡すことを許可しています。
<div>
<%=f.label :genre_ids, "ジャンル機能" %>
<span>
<% Genre.all.each do |genre| %>
<%= f.check_box :genre_ids,
{ multiple: true, checked: @sauna.genres.find_by(id: genre.id).present?,
include_hidden: false }, genre[:id] %>
<label class="form-check-label">
<%= genre.name %>
</label>
<% end %>
</span>
</div>
form.check_box :label_ids
→ paramsの値として、"label_ids"=>["1", "2", "3"]
このような形でハッシュのキーを持つ値を送れます。
multiple
オプションを使用することで、複数のチェックボックスのパラメータを配列形式で送れます。
checked: @task.labels.find_by(id: label.id).present?
これは編集画面等で登録されているラベル
にチェックを付けるということをしています。
include_hidden: false
→登録のない項目については、パラメータを送らないメソッドです。
このまま実装すると一見複数中間テーブルも作成できるし、編集の時もしっかりチェックついてるし問題ないと思っていたのですが、編集画面でチェックを全て外して更新してもジャンルの複数の名前は消えなかったのです。
何が原因か、、、この実装方法だと、空で送ってしまうと値としてnilが返ってきてしまいます。
それを解決するためにストロングパラメーターを少し工夫します。
#省略
def sauna_params
values = params.require(:sauna).permit(
:name,
genre_ids: []
)
if values[:genre_ids].nil?
values[:genre_ids] = []
end
return values
end
このようにすることでgenre_idsにもしnilが返ってきた時に空の配列を送ることでジャンルを持たないものも作成することができました。
ジャンルを作っている以上、ジャンルなしということはないとは思いますが、気づいたので備忘録として残しておきます。
ありがとうございました