テーブルアソシエーション (Rails4)
[最終更新] (2019/06/03 00:45:00)
最近の投稿
注目の記事

概要

モデル間に従属関係がある場合、モデルにアソシエーションを記述して関係性を明示しておくことで、テーブルをjoinするSQLをRailsのActiveRecordが自動的に裏で実行してくれるようになり、直感的な情報アクセスが可能になります。

belongs_to

usersテーブル

commentsテーブル

  • 「user_id」を外部キーとして持っている
  • "A comment belongs to a user."

app/models/comment_model.rb

class CommentModel < ActiveRecord::Base
  belongs_to :user # ←単数形
end

has_many

belongs_to とは逆の概念です。主従関係は同じであり、テーブル構成も同じです。以下のようなメソッドが使用できるようになります。

  • @user.comments
  • @user.comments.size
  • @user.comments.empty?
  • @user.comments.find(1) # id=1
  • @user.comments.exist?(1) # id=1
  • @user.comments.destroy(@comment)
  • @user.comments.clear # すべて削除
  • @user.comments<<@comment # ユーザのコメントを追加
  • @user.comments = @new_comments # ユーザのコメントを一括登録
  • @comment = @user.comments.build(title: 'Abc') # 保存しない。「@comment.save」と続ける
  • @user.comments.create(title: 'Abc') # 保存する

usersテーブル

  • "A user has many comments."

app/models/user_model.rb

class UserModel < ActiveRecord::Base
  has_many :comments # ←複数形
end

commentsテーブル

  • 「user_id」を外部キーとして持っている

has_one

belongs_to の特殊な場合における逆の概念です。主従関係は同じであり、テーブル構成も同じです。特殊な場合とは、異なる二つのものが、同じものにbelongしないことが保証されている場合のことを差します。以下のようなメソッドが使用できるようになります。

  • @user.comment = @comment # あるユーザのcommentとして@commentを登録 (commentのuser_idにuserのidを設定)
  • @comment = @user.build_comment(title: 'Abc') # commentを作成し、そのuser_idに@userのidを設定) (保存しない @comment.saveと続く)
  • @user.create_comment(title: 'Abc') # commentを作成し、そのuser_idに@userのidを設定) (保存する)

usersテーブル

  • "A user has one comment."

app/models/user_model.rb

class UserModel < ActiveRecord::Base
  has_one :comment # ←単数形
end

commentsテーブル

  • 「user_id」を外部キーとして持っている

「has_one」と「belongs_to」の関係において、どちらのテーブルに外部キーを持たせるかは、それらの主従関係を考えて決定します。「has_one」する側は他方を必要としません。「belongs_to」する側は自分が存在のために他方を必要とします。

has_and_belongs_to_many

多対多の場合です。主従関係はありません。中間テーブルが必要となります。中間テーブルの名称は、参照先テーブルを辞書順にアンダーバー '_' でつなげたものとします。中間テーブルに独自の情報列は作成せず、したがって対応するモデルも不要です。HBTMとも称します。以下のようなメソッドが使用できるようになります。

  • @user.comments
  • @user.comments.size
  • @user.comments.empty?
  • @user.comments.find(1) # id=1
  • @user.comments.exist?(1) # id=1
  • @user.comments.destroy(@comment)
  • @user.comments.clear # すべて削除
  • @user.comments<<@comment # ユーザのコメントを追加
  • @user.comments = @new_comments # ユーザのコメントを一括登録
  • @comment = @user.comments.build(title: 'Abc') # 保存しない。「@comment.save」と続ける
  • @user.comments.create(title: 'Abc') # 保存する

authorsテーブル

app/models/author_model.rb

class AuthorModel < ActiveRecord::Base
  has_and_belongs_to_many :books
end

booksテーブル

app/models/book_model.rb

class BookModel < ActiveRecord::Base
  has_and_belongs_to_many :authors
end

authors_booksテーブル

  • 「author_id」および「book_id」を列として持ちます

has_many through

「has_and_belongs_to_many」において、中間テーブル自体は情報を有さず、したがってモデルも存在しませんでした。そうではなく、情報を有する存在意義のあるモデルが中間となり、二つのモデルに「has_and_belongs_to_many」の関係を与える場合は「has_many through」を使用します。

usersテーブル

app/models/user_model.rb

class UserModel < ActiveRecord::Base
  has_many :reviews
  has_many :books, through: :reviews
end

reviewsテーブル

app/models/review_model.rb

class ReviewModel < ActiveRecord::Base
  belongs_to :user
  belongs_to :book
end

booksテーブル

app/models/book_model.rb

class BookModel < ActiveRecord::Base
  has_many :reviews
  has_many :users, through: :reviews
end

カウンターキャッシュ

この続きが気になる方は

テーブルアソシエーション (Rails4)

残り文字数は全体の約 22 %
tybot
100 円
関連ページ
    概要 こちらのページで使い方を把握した MyBatis を、こちらのページで使い方を把握した Spring Boot で利用するための基本的な設定およびサンプルコードをまとめます。サンプルコードにおいては、特に MySQL を対象とします。 MyBatis Spring-Boot-Starter チュートリアル