【Rails初心者向け】モデル間の関連付け(アソシエーション)まとめ

  • 29
    Like
  • 0
    Comment
More than 1 year has passed since last update.

目次

■アソシエーションとは
■belongs_to
■has_many
■has_one
■has_many through
■まとめ

アソシエーションとは

テーブル間リレーションシップをモデル上の関係として扱う仕組みです。
【アソシエーション = モデル間の関連付け】
といった具合に認識しておけば良いのではないかと思います。
テーブル間の関係には、具体的にどんな関係が存在するのかをあげると、
おおよそ
【1:1, 1:n, m:n】
に分けられるのではないかと思います。
今回は、この関係についてそれぞれ見ていきます。

belongs_to

【参照元テーブルから参照先テーブルの情報にアクセスする】
例として、reviewモデルとbookモデルを使って、
belongs_toアソシエーションについて見ていきます。

review.rb
class Review < ActiveRecord::Base
  belongs_to :book
end

belongs_toで
いまのモデル(reviewモデル)から指定したモデル(bookモデル)を参照します。
ということを宣言できます。

review/index.html.erb
<h1><%= @review.book.title %><h2>
<p><%= @review.body %></p>

といった具合に、
Reviewクラスのインスタンスから
@review.book.titleというカタチで、書籍のタイトルを参照できるようになります。

has_many

先ほどのbelongs_toアソシエーションで、参照元→参照先の関係を作ることができました。
has_manyアソシエーションでは、
【1:nの関係を表す】ことが出来ます。
先ほど同様に、bookクラスとreviewクラスを例にあげるとすると、
reviewクラスがbookクラスを参照しますという関係を表すことでできたのが、belongs_toであるのに対して、
1つのbookオブジェクトに対して、複数のreviewオブジェクトが存在するという関係を表すことが出来ます。

book.rb
class Book < ActiveRecord::Base
  has_many :reviews
end

これで準備完了。

book/index.html.erb
<h1><%= @book.title %>のレビュー<h2>
<ul>
<% @book.reviews.each do |r| %>
  <li><%= r.body %></li>
<% end %>
</ul>

has_manyを設定したことで、belongs_to同様、プロパティのように関連するオブジェクトを取得できるようになりました。
今回の場合、belonga_toと違って、reviewsメソッドの戻り値が配列になります。

has_one

【1:1の関係を表すことができるアソシエーション】です。
userモデルとauthorモデルを使って、考えてみます。

user.rb
class User < ActiveRecord::Base
  has_one :author
end
author.rb
class Author < ActiveRecord::Base
  has_one :user
end

以上で、設定は完了です。

has_many through

【m:nの関係を表すアソシエーション】です。
いままでのアソシエーションに比べて、やや複雑な気もしますが、
本質的なことは先程と何も変わりません。
bookモデルとuserモデルがreviewモデルを間にとって、m:nの関係にある場合を見ていきます。

book.rb
class Book < ActiveRecord::Base
  has_many :reviews
#reviewモデルを間に取って、userモデルと関連付ける
  has_many :users, through: :reviews
end
user.rb
class User < ActiveRecord::Base
  has_many :reviews
#reviewモデルを間に取って、bookモデルと関連付ける
  has_many :books, through: :reviews
end

reviewモデルも、book/userモデルとそれぞれ関連付けをします。

review.rb
class Review < ActiveRecord::Base
  belongs_to :book
  belongs_to :user
end

以上で、bookモデルとuserモデルにおいて、m:nの関連付けを設定出来ました。

@user.booksといった具合に扱うことが可能です。
以下の図解でみると関係がわかりやすいと思います。
(出典:Railsガイド)
has_many_through.png

has_many throughアソシエーションについては、
http://ruby-rails.hatenadiary.com/entry/20141204/1417688260
以下のHatena Blogでも詳しく書いてありました。

まとめ

アソシエーションを使いこなすことで、複数のモデル(テーブル)のまたがるデータを、非常にわかりやすく簡単に扱うことができます。
belongs_to, has_many, has_one, has_many throughそれぞれについて、関係をイメージできるようにすることが大切だと思いました。

以前、belongs_toについてのみ書いた記事です。
【エンジニア初心者が学んだ】belongs_toアソシエーションについて

参考資料

Railsドキュメント(リファレンス)
http://railsdoc.com/references

Ruby on Railsガイド
http://railsguides.jp/

Ruby on Rails 4 アプリケーションプログラミング, 山田 祥寛
http://www.amazon.co.jp/dp/4774164100

パーフェクト Ruby on Rails, すがわら まさのり
http://www.amazon.co.jp/dp/4774165166