4

我们的 Rails 3 应用程序有模型PersonMessage. 消息可以特定于某个人(当person_id设置了消息列时),也可以是“全局的”(当person_id列为 NULL 时)。

我们希望使用以下选项has_many建立一个简单的关系::conditions

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

但似乎has_many在强制外键约束与 Person 对象的 id 相等(例如“ FROM messages WHERE person_id=123 AND (person_id IS NULL OR person_id=123)”)之后,类方法将“条件”选项编码为逻辑“AND”子句。似乎没有办法允许具有空外键的关联对象属于此类关联。

Rails 3 / ActiveRecord 是否提供了一种方法来做到这一点,还是我必须破解我自己的类似关联的方法?

4

2 回答 2

1

您不能像在 ActiveRecord 关联中使用条件那样拥有 OR 子句。您可以在没有条件的情况下进行关联,然后添加一个方法来包含您想要的全局消息。这样,您在构建关联记录时仍然可以利用关联。

# person.rb
has_many :messages

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

这是我的Squeel gem的标准插件,如果您不想在代码中包含一些 SQL,它对于像这样的更高级的查询很方便。一探究竟。

于 2012-05-03T16:28:47.080 回答
0

我认为您是正确的,您可以放弃 has_many,并使用外部连接创建一个范围,例如:

class Person < ActiveRecord::Base
   scope :messages lambda { 
      joins("RIGHT OUTER Join messages on persons.id = messages.person_id")
      .where('persons.id = ?',self.id)
   }
于 2012-05-03T15:07:16.927 回答