1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

formオブジェクトでの中間テーブルを利用した複数選択できるチェックボックス機能の実装

Posted at

初めに

疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。

開発環境:
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
db/seeds.rb
# ここでcolorの初期データを作成します。

names = %w[赤 黄 黒 白]
names.each do |color_name|
  Color.find_or_create_by(name: color_name)
end

db:seedをして、準備完了です!

formオブジェクトのファイル作成

app/forms/example_form.rb
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メソッドの構造確認

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?