简体   繁体   中英

Rails “has_many” association with NULL foreign key

Our Rails 3 application has models Person and Message . Messages can be specific to a Person (when the message person_id column is set) or they can be "global" (when the person_id column is NULL).

We would like to have a simple has_many relationship using the :conditions option as such:

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

But it appears that the has_many class method encodes the "conditions" option as a logical "AND" clause after enforcing the foreign key constraint of equality to the Person object's id (eg " FROM messages WHERE person_id=123 AND (person_id IS NULL OR person_id=123) "). It appears that there is no way to allow associated objects with null foreign keys to belong to such associations.

Does Rails 3 / ActiveRecord provide a way to do this or must I hack my own association-like methods?

You can't have an OR clause like you want using conditions on the ActiveRecord assocation. You could have the association without conditions and then add a method to include the global messages you want. That way you could still take advantage of the association when building associated records.

# person.rb
has_many :messages

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

Here's my standard plug for the Squeel gem, which is handy for more advanced queries like this if you don't want to have bits of SQL in your code. Check it out.

I think you're correct, you could forgo has_many, and create a scope with an outer join, something like:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM