似乎无法解决这个问题。我在下面有一个消息模型
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?我现在被困住了。
任何帮助非常感谢
答案 0 :(得分: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使用它。