QKAKE::TECH

テックなことを書く

Active Recordの関連付け機能(アソシエーション)を活用する【Rails】

コードをシンプルにかくことができるアソシエーションとは?

数カ月前からRuby on Railsを用いてWebアプリケーションを作ってきたのですが、ここにきてアソシエーションの便利さに気づき始めました。
アソシエーションとはモデルとモデルの間に関連付けを行なうことです。
これをすることで、コード内で一般的に行われる操作をはるかにシンプルにすることが可能となります。

「has_many」と「belongs_to」でみる関連付け

今回は関連付けの中でも「has_many」と「belongs_to」を見ていきたいと思います。
仮にBookモデルとBookReviewモデルがあったとします。
このケースで、一つの書籍に対して複数のレビューを持つと宣言したい場合、以下のようにモデルに記述してあげます。

class Book < ActiveRecord::Base
  has_many :book_reviews
end

has_many関連付けは、他のモデルとの間に「1対多」のつながりがあることを示します。has_many関連付けが使用されている場合、「反対側」のモデルではbelongs_toが使用されることが多くあります。

class BookReview < ActiveRecord::Base
  belongs_to :book
end

あるモデルでbelongs_to関連付けを行なうと、他方のモデルとの間に「1対1」のつながりが設定されます。このとき、宣言を行ったモデルのすべてのインスタンスは、他方のモデルのインスタンス「従属(belongs to)」します。

Controllerのソースがシンプルになる

さて、こうしてあげることで何が便利なのかというとcontrollerの書き方がシンプルになるのです。
例えば、本のID=1のときのレビューを取得するために次のように書いていたとします。

@book = Book.find(1)
@book_reviews = BookReview.where(book_id: @book.id)

これは書籍情報とレビューとの対応関係が、booksテーブルのid列book_reviewsテーブルのbook_id列によって表現されている例です。
booksテーブルのid列は、書籍情報を一意に識別するための主キーと呼ばれます。
book_reviewsテーブルのbook_id列には、books.id列に対応する値を設置することで、レビューがどの書籍と紐付いているのかを表しています。ちなみに、このような参照キーのことを外部キーと呼びます。
すみません、少し脱線してしまいました。
上のコードをアソシエーションを使用することで次のように書くことが出来るのです。

@book = Book.find(1)
@book_reviews = @book.book_reviews

いかがでしょう。直感的な書き方になりました。
Railsのレールに乗っかってテーブルのフィールド名を「book」と「book_id」といったものにすることができれば一番簡潔ですが、そうはいかない(関連付けを指定したい)ときもあると思います。
そういうときのために、次のような関連付けの仕方が用意されています。

アソシエーションにおける外部キーの指定

class Book < ActiveRecord::Base
  has_many :author_categories, foreign_key: 'category_1'
  belongs_to :parent_category, class_name: "Category", foreign_key: "category_1"
  belongs_to :child_category, class_name: "Category", foreign_key: "category_2"
end

「belongs_to」に実際にcontrollerで使用したい名前を記述し、そして「class_name」にクラス名、「foreign_key」に外部キーをそれぞれ指示してあげることで、これを使用することができるようになるのです。

上の書籍の例は単純なものなのであまり違いがないように感じられるかもしれませんが、複数のテーブルとの結合が必要となってきたときなど、このアソシエーションの真価を見ることが出来ます。
これまでボクはcontrollerでjoinsメソッドを用いて、LEFT JOINを何度もしていたのですが、アソシエーションを利用することで、たとえばuser.book.prices.last.priceで「ユーザーが登録している書籍の最大価格を取得する」といったようなことができるようになりました。

できるだけrailsの哲学である「設定より規約」に従ってよりシンプルにコードを書いていきたいものです。


宣言
アソシエーションの確認の意味も込めて、明日からはRuby on Railsチュートリアルを読み進めていきたいと思います。

参考

Ruby on Rails 4 アプリケーションプログラミング

Ruby on Rails 4 アプリケーションプログラミング

Ruby on Railsを始めるならまずこれ。
あと、書籍ではなくWebサービスですが、Progateがプログラミングの導入におすすめです。Railsコースも最近できました。