[Rails] has_many関連の結合条件を動的に指定する方法

※ 2013/5/21 追記

本記事に対してTwitterで以下のような意見をいただきました。

おっしゃるとおりです。この方法だとマルチスレッド環境で変数の値が保証されません。なので、この記事に書いてある内容は真似しないでくださいね。


Rails 3.2を最近使い始めたkadoppeです。こんにちは。

今日は、Railsアプリのモデルにおいて、has_many関連の結合条件を動的に指定する方法を覚えたので、紹介したいと思います。

当方の環境は ruby 1.9.3 + Rails 3.2.1 です。

結合条件を静的に指定する方法

まずは、静的に指定する方法から。「conditions」オプションを使うことで、has_many関連の結合条件を指定することができます。

下の例では、レクチャーを表す「Lecture」モデルと、ユーザーごとの学習状況を表す「LectureStatus」モデルがあった場合に、Lectureモデルのオブジェクトに「ID:1」のユーザの学習状況のみを関連付けています。

結合条件を動的に指定する方法

では、上の例を発展させて、「Webサイトに現在ログインしているユーザーの学習状況」のみをLectureモデルに関連付けたい場合を考えてみます。そのためには、結合条件を動的に指定する必要がありますね。

以下のように、「:conditions」オプションに対してProcを渡すことで、条件を動的に指定することができます。

例えば、もう少し書き足して、

のようにして、コントローラから

のように呼び出してやれば、「@lecture」オブジェクトの中にはすべてのレクチャーの情報と、それらに関するログインユーザーの学習状況が含まれていることになります。

めでたしめでたし。

まとめ

結合条件を動的に指定できるようになったことで、今までよりもよりシンプルにコードが書けるようになりそうです。

参考にさせていただいた以下の記事によると、has_many関連だけではなくbelongs_toやhas_one関連でも同様のことが実現できるみたい。

みなさんもぜひお試しください。

それではー。

  • kozo002

    とても参考になりました。

    ちなみに
    :conditions => Proc {“user_id…
    の部分は
    :conditions => Proc.new {“user_id…
    じゃないとNoMethodErrorでした。