2

似乎无法解决这个问题。我在下面有一个消息模型

Message
 # content:string
 # original_id:integer
 # sender_id:integer
 # receiver_id:integer

 has_one :reply, class_name: "Message", foreign_key: "original_id"
 belongs_to :original, class_name: "Message"

每条消息只能有一个回复,回复消息会有对应的原始消息。

我想做的是创建一个范围或类方法,允许我在一批中提取已回复的消息,并在另一批中提取未回复的消息。

就像是

 # return messages that have a reply present
 def self.replied
   where(reply.present?)
 end

 # return messages that have no reply
 def self.unreplied
   where(reply.nil?)
 end

所以我可以链接方法并最终拉出消息

 user1.messages.replied

它目前不起作用,因为我不能使用 where 子句,除非它是一个 DB 列......所以我正在考虑在 DB 中添加一个“replied”布尔列,这样我就可以使用 where 子句但可能有一个解决方案对此,我只是没有考虑。带有 lambda 的作用域?我现在被困住了。

非常感谢任何帮助

4

1 回答 1

6

查找已回复的内容相当简单:

scope :replied, joins(:reply)

因为任何没有回复的东西都会被 INNER JOIN 过滤掉。要找到没有回复的人有点复杂——您可以使用 LEFT JOIN 或 EXISTS 子查询来完成此操作。 includes是一种强制 LEFT JOIN 的简单方法:

scope :unreplied, includes(:reply).
                  where(replies_messages: {id: nil}).
                  where(original_id: nil)

EXISTS 子查询可能更有效,但编写起来更复杂(此时),因为它涉及调用 Arel 表(或 Squeel)。在大多数情况下,LEFT JOIN 将“足够好”,并且includes是强制 API 使用它的一种快速而肮脏的方式。

于 2013-06-27T16:13:50.203 回答