0
0

フォロー機能と同じテーブル構造で複数チェックボックスの管理方法を考えてみた

Last updated at Posted at 2023-10-02

実現したいこと

同じテーブル同士で1つのに対して、複数の同じテーブルのレコードを紐づけてチェックボックスで登録できるようにする。
例えば、

  • ユーザーの一括お気に入り機能
  • 一括ブロック機能
  • アイテムをひとまとめにするアイテム

などが挙げられます。

記事にした経緯として、

  • 探しても実装事例が全く見つからなかった
  • この発想に至るまでハマって時間を無駄にした

というものからです。

開発環境

  • Ruby 3.0.2
  • Rails 7.0.3.1

オーソドックスな管理方法

よくある例として車とパーツの関係でテーブル設計をしてみました。
利用例としては、車に対して装着したいカスタムパーツにチェックを入れる想定です。

※ストロングパラメーターの設定は、実装例が多くあるため割愛しております。

テーブル設計

cars

カラム名
id integer
name string

car_parts

カラム名
car reference
part reference

parts

カラム名
id integer
name string
  • carモデル
class Car < ApplicationRecord
  has_many :car_parts, dependent: :destroy
  has_many :parts, through: :car_parts

  accepts_nested_attributes_for :car_parts, allow_destroy: true
end

  • 中間テーブルとなるcar_partモデル
class CarPart < ApplicationRecord
  belongs_to :car
  belongs_to :part
end
  • partモデル
class Part < ApplicationRecord
  has_many :car_parts, dependent: :destroy
  has_many :cars, through: :car_parts

  accepts_nested_attributes_for :car_parts, allow_destroy: true
end

チェックボックスとして表示させるフォーム

= form_with model: @car, local: true do |f|
  = f.fields_for :car_parts do |l|
    = l.collection_check_boxes :part_ids, Part.all, :id, :style, checked: @car.part_ids ,include_hidden: false do |b|
      label { b.check_box + b.text }
  = f.submit

本題

同じテーブル間でチェックを入れて追加し合う場合
アイテムをひとまとめにする機能を例に挙げてみます。

テーブル設計

items

カラム名
id integer
name string

item_relations

カラム名
item reference
item_selection reference

item_selection(クラス継承)
理解しやすくするための便宜上、テーブル設計に挙げています。

カラム名
Itemテーブルと同じ Itemテーブルと同じ

itemモデル

item.rb
class Item < ApplicationRecord
  has_many :item_relations, dependent: :destroy
  has_many :item_selections, through: :item_relations

  accepts_nested_attributes_for :item_relations, allow_destroy: true
end
  • 中間テーブルとなるitem_relationモデル
item_relation.rb
class ItemRelation < ApplicationRecord
  belongs_to :item
  belongs_to :item_selection, class_name: 'Item'
end

単一テーブル継承(STI)を使って
Itemクラスを継承したItemSelectionクラスを用意

item_selection.rb
class ItemSelection < Item
  has_many :item_relations, dependent: :destroy
  has_many :items, through: :item_relations

  accepts_nested_attributes_for :item_relations, allow_destroy: true
end

チェックボックスとして表示させるフォーム

= form_with model: @item, local: true do |f|
  = f.fields_for :item_selections do |l|
    = l.collection_check_boxes :item_selection_ids, ItemSelection.all, :id, :style, checked: @item.item_selection_ids ,include_hidden: false do |b|
      label { b.check_box + b.text }
  = f.submit

コンパクトに実装ができました🎉

参考記事

非常にわかりやすい構成で執筆の際に参考にさせていただきましたmm

0
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
0
0