LoginSignup
3
0

More than 3 years have passed since last update.

has_and_belongs_to_manyメソッドを使用してモデルを関連付けする

Posted at

has_and_belongs_to_manyメソッドを使って多対多のモデルの関連付けからレコードを作成するまでの手順を書いていきます。

記事執筆時のRailsとRubyのバージョンは以下のとおりです。

$ rails -v
Rails 6.0.3.1
$ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin18]

has_and_belongs_to_many関連付け

has_and_belongs_to_many関連付けでは、多対多のモデルをつなぐ中間テーブルを作成します。has_many :through関連付けのように中間モデルは作成しません。

モデルの関連付けのイメージ図(Railsガイドから引用)
Active Record の関連付け - Railsガイド
image.png

assembliesとpartsが多対多で関連付けるモデルで、assemblies_partsがそれらの中間テーブルです。

モデルの関連付け

上記のモデルを以下のように具体化して説明します。
assembliesモデル→Userモデル
partsモデル→Bookモデル
assemblies_parts→books_usersテーブル

ユーザー(User)が読んだ本(Book)を登録するアプリを作成するとします。
1人のUserは複数のBookを登録でき、同じBookは複数のUserから登録されるため、多対多の関係になります。

UserモデルとBookモデルを関連づけるために、それぞれのモデルに以下の定義を追加します。

class User < ApplicationRecord
  (中略)
  has_and_belongs_to_many :books
end
class Book < ApplicationRecord
  (中略)
  has_and_belongs_to_many :users
end

UserとBookを紐づけるために中間テーブルを作成します。モデルは作成しないので、マイグレーションファイルのみ作成します。

rails g migration create_books_users book:references user:references

マイグレーションファイルが作成されるので、rails db:migrateを実行します。

class CreateBooksUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :books_users do |t|
      t.references :book, null: false, foreign_key: true
      t.references :user, null: false, foreign_key: true
    end
  end
end

レコードの作成

本(Book)を登録するアクションをコントローラーに作成します。

以下の例ではbuildメソッドでBookオブジェクトの作成、saveメソッドでBookオブジェクトをDBに保存、<<メソッドで中間テーブルにレコードを作成しています。
buildメソッド、<<メソッドはhas_and_belongs_to_manyで宣言したことにより使えるようになるメソッドです。
Bookオブジェクトの作成とDBへの保存の処理を分ける必要がない場合は、buildメソッドと<<メソッドの代わりにcreateメソッドを使ってオブジェクトの作成から保存までまとめて実行することもできます。
has_and_belongs_to_manyで追加されるメソッド - Railsガイド

class BooksController < ApplicationController
  (中略)
  def create
    # 登録するBookのレコードに紐づけたい任意のUserオブジェクトをインスタンス変数に設定
    @user = User.first
    # Userと紐づくBookオブジェクトを作成(book_paramsはストロングパラメーター)
    @book = @user.books.build(book_params)

    # DBに保存
    if @book.save
      # 中間テーブルにレコードを作成
      @user.books << @book 
      redirect_to @book
    else
      render :new
    end
  end
  (中略)
end
3
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
3
0