初めに
疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。
開発環境:
Rails7.1.3
ruby3.3.6
目的
formオブジェクトを通して多対多の関係のモデルを使用して複数のチェックボックスで保存できるようにする。
前準備(モデルのリレーション、初期データ)
class Example < ApplicationRecord
has_many :example_colors, dependent: :destroy
has_many :colors, through: :example_color
end
class ExampleColor < ApplicationRecord
belongs_to :color
belongs_to :example
end
class Color < ApplicationRecord
has_many :example_colors
has_many :examples, through: :example_colors
end
# ここでcolorの初期データを作成します。
names = %w[赤 黄 黒 白]
names.each do |color_name|
Color.find_or_create_by(name: color_name)
end
db:seedをして、準備完了です!
formオブジェクトのファイル作成
class ExampleForm
include ActiveModel::Model
include ActiveModel::Attributes
attr_accessor :title, :body, :color_ids
delegate :persisted?, to: :example
def initialize(attributes = nil, example: Example.new)
@example = example
attributes ||= default_attributes
Rails.logger.debug "Initializing ExampleForm with: #{attributes.inspect}"
super(attributes)
end
def to_model
example
end
def save
ActiveRecord::Base.transaction do
example.update!(title: title, body: body, color_ids: color_ids.reject(&:blank?))
end
end
praivate
attr_reader :example
def default_attributes
{
title: example.title,
body: example.body,
color_ids: example.color_ids
}
end
end
idsモデルを使うと、関連オブジェクトのidの取得、追加・削除を行えます。
関連自体の操作で楽にデータ管理できるわけですね。
コントローラ作成
class ExamplesController < ApplicationController
def new
@form = ExampleForm.new
end
def create
@form = ExampleForm.new(example_params)
if @form.valid?
@form.save
end
end
praivate
def example_params
params.require(:example).permit(:title, :body, color_ids:[])
end
end
formの作成
<%= form_with model: @form, local: true |f| %>
<div class="mb-3">
<%= f.label :タイトル %>
<%= f.text_field :title %>
</div>
<div class="mb-3">
<%= f.label :本文 %>
<%= f.text_field :body %>
</div>
<div>色</div>
<%= f.collection_check_boxes :color_ids, Color.all, :id, :name do |b| %>
<div>
<%= b.label { b.check_box + b.text } %>
</div>
<% end %>
<%= f.submit '登録' %>
<% end %>
collection_check_boxesメソッドを使用してチェックボックスを作成します。
form_withの中なので第一引数は省略しています。
第二引数にcolor_idsをセット。メソッド名を指定しています。
第三引数にColor.allをセット。チェックボックス作成の際どこからデータを取るか指定します。
第四引数にidをセット。valueを指定しています。
第五引数にnameをセット。こちらはチェックボックスのtextを指定していますね。
これでformオブジェクトを使用しながら複数のチェックボックスで、複数のチェックを入れられるフォームの完成です!
参考記事
Railsのデザインパターン: Formオブジェクト
1.5. 多対多の関連を持つオブジェクトをチェックボックスで編集可能なフォーム
collection_check_boxesメソッドの構造確認