LoginSignup
6
7

More than 3 years have passed since last update.

【Rails】多対多のカテゴリー機能の実装

Posted at

目標

ezgif.com-video-to-gif (1).gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
Bootstrap3導入
投稿機能実装
カテゴリー機能実装

実装

1.中間テーブルを作成

ターミナル
$ rails g model BookCategory book_id:integer category_id:integer
ターミナル
$ rails db:migrate
schema.rb
create_table "book_categories", force: :cascade do |t|
  t.integer "book_id"
  t.integer "category_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

2.カラムを削除

ターミナル
$ rails g migration RemoveCategoryIdFromBooks category_id:integer
~_remove_category_id_from_books
class RemoveCategoryIdFromBooks < ActiveRecord::Migration[5.2]
  def change
    remove_column :books, :category_id, :integer
  end
end
ターミナル
$ rails db:migrate

3.各モデルを編集

book.rb
has_many :book_categories
has_many :categories, through: :book_categories
category.rb
has_many :book_categories
has_many :books, through: :book_categories
book_category.rb
# 追記
belongs_to :book
belongs_to :category

4.コントローラーを編集

books_controller.rbのストロングパラメーターでcategory_idを配列可にする。

books_controller.rb
def book_params
  params.require(:book).permit(:title, :body, { category_ids: [] })
end

5.ビューを編集

①フォームを編集

books/index.html.slim
/ 変更前
= f.label :category_id, 'カテゴリー'
br
= f.collection_select :category_id, Category.all, :id, :name, { prompt: '選択してください' }, class: 'form-control'
br

/ 変更後
= label_tag 'カテゴリー'
br
= collection_check_boxes(:book, :category_ids, Category.all, :id, :name) do |cb|
  = cb.label { cb.check_box + ' ' + cb.text }
br

= collection_check_boxes(:book, :category_ids, Category.all, :id, :name) do |cb|
➡︎ 全カテゴリーの名前をチェックボックスとして表示し、値をidに設定している。

②テーブルを編集

books/index.html.slim
/ 変更前
td
  = category.name

/ 変更後
td
  - book.categories.each do |category|
    = category.name
    | /
6
7
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
6
7