2012-05-03 22 views
4

私たちのRails 3アプリケーションはPersonMessageのモデルを持っています。メッセージは、メッセージにperson_id列が設定されている場合はPersonに固有のメッセージ、またはperson_id列がNULLの場合はグローバルになります。Rails "foreign_key"との "has_many"関連

我々が使用して簡単なhas_many関係を持ちたい:conditions optionなど:

class Person < ActiveRecord::Base 
    has_many :messages, 
     :conditions => proc { ['(messages.person_id IS NULL) OR ' + 
          '(messages.person_id = ?)'], self.id } 
    # ... 
end 

しかし、has_manyクラスメソッドを強制した後に論理「AND」句などのオプションを「条件」をコードしていることが表示されますPersonオブジェクトのidと等しい外部キー制約(例: "FROM messages WHERE person_id=123 AND (person_id IS NULL OR person_id=123)")。ヌルの外部キーを持つ関連オブジェクトがそのような関連に属することを許可する方法はないようです。

Rails 3/ActiveRecordはこれを行う方法を提供していますか、私自身の関連付けのようなメソッドをハックする必要がありますか?あなたは上の条件を使用したいようにあなたがOR句を持つことができません

class Person < ActiveRecord::Base 
    scope :messages lambda { 
     joins("RIGHT OUTER Join messages on persons.id = messages.person_id") 
     .where('persons.id = ?',self.id) 
    } 

答えて

1

:私はあなたが正しいなら、あなたはhas_manyのを見送ると、外側にスコープを作成することができると思い

+0

残念ながら、これは、all_messagesが関連ではないため、Person.limit(2).includes(:all_messages)のようなことはできません。 –

+0

@JoeVanDykはい、そうです。しかし、includes(:all_messages)を実行すると、eager-loadingを実行するために余分なSQLクエリが実行されます。シンタックスを超えても、私の提案とパフォーマンスの点では大きな違いはありません。 –

+0

includes(:all_messages)を実行すると、最大で1つの追加クエリが発生します。 Person.limit(100).includes(:all_messages)を実行した場合は、2つのクエリが発生します。上記の#all_messagesを使用した場合は、すべてをロードするために101クエリになります。 –

0

は、のようなものに参加しますActiveRecordアソシエーション。条件なしで関連付けることができ、必要なグローバルメッセージを含める方法を追加できます。そうすれば、関連付けられたレコードを作成するときに、関連付けを利用することができます。

# person.rb 
has_many :messages 

def all_messages 
    Message.where('messages.person_id=? OR messages.person_id IS NULL', id) 
end 

ここでは、あなたのコード内でSQLのビットを持ってしたくない場合は、このような、より高度なクエリに便利ですSqueel宝石、私のための標準プラグです。見てみな。

関連する問題