2011年12月15日木曜日

[Rails3] belongs_to で関連づけたモデルの属性値でソートするには :include を使うのだ

実行環境:
Rails 3.1.3
Rails3で、belong_to で関連付けられたモデルが持っている属性値でソートするには?

例として以下のように「本(Book)」モデルと「著者(Author)」モデルがあったとします。
{$RAILS_APP}/app/models/authors
class Author < ActiveRecord::Base has_many :books end
{$RAILS_APP}/app/models/books
class Book < ActiveRecord::Base belongs_to :Author end
2つのモデルは、has_many, belongs_to で関連づけられています。
本(Books)のリストを取得する際に著者(Author)の名前の順にソートしたいと思います。

まずは試しに
{$RAILS_APP}/app/models/books
class Book < ActiveRecord::Base belongs_to :Author default_scope :order => "author.name" end
と、has_many / belongs_to の関連付けの力を信じて、うまくやってくれるだろうと期待してみる訳ですが Book.find すると「そんなカラムは知らんぞ!」とエラーが出て怒られます。

ログを見ても Book リストの取得の際の SQL 文に Author テーブルが全く登場しません。
author.name を order by のキーとして与えているところを汲んで欲しいところですが、そこまでは面倒見てくれない、ということでしょうか。

こんな時、他のテーブルを強制的に join させる素敵なコマンドがあります。 :include です。
{$RAILS_APP}/app/models/books
class Book < ActiveRecord::Base belongs_to :Author default_scope :include => "author", :order => "author.name" end
としてやると、authorテーブルを強制的に join してくれるので上記のソートもうまくいくようになります。

2 件のコメント:

  1. 私の環境では
    default_scope :include => author, :order => "author.name"
    だとエラーになり、
    default_scope :include => "author", :order => "author.name"
    だと上手くいきました。
    参考までに。

    返信削除
    返信
    1. たしかに文字列にしてあげないと値が nil の変数として扱われてしまいますね。ご指摘ありがとうございます。

      削除