2015-09-03 50 views
0

说我有这个简化的模型设置如何查找没有关联的数据库记录?

用户:

has_many :logs 

登录:

attr_accessible :key, :value 
belongs_to :user 

当用户接触,应用程序创建了

Log.create(user: user, key: "contacted", value: "by admin") 
日志此事件

有许多其他类型的日志,由t继承人key属性值。

我想写一个范围,将返回所有从未联系过的用户。
到目前为止,我有

scope :never_contacted, -> { joins(:logs).where.not("logs.key = ?", "contacted").uniq } 

不幸的是,这似乎只返回比“接触”等日志,并留下了具有完全没有日志的用户。

我想有可能以“反”积极的查询,例如

scope :contacted, -> { joins(:logs).where("logs.key = ?", "contacted").uniq } 
scope :never_contacted, -> { (all - contacted) } 

但我也怀疑这样的做法是非常低效的。

是否有可能查询没有与“contacts”关联的日志作为关键属性的用户?

回答

2

可以通过单个SQL查询来实现更正结果,但您需要一点良好的旧SQL。

User.joins("LEFT JOIN logs ON logs.user_id = users.id").where("logs.id IS NULL") 

上述代码强制LEFT JOIN(如由缺省AR创建INNER JOIN)和获取所有在没有相应日志中的logs表中的用户。

你可以打包为一个范围

scope :never_contacted, -> { joins("LEFT JOIN logs ON logs.user_id = users.id").where("logs.id IS NULL") } 
+0

此查询不会只返回没有日志的用户吗?那些除了“联系”之外还有其他日志的用户呢? – Epigene

+1

只需在WHERE中添加一个额外的OR条件。 –

0

我查询SQL直接与OR条件,如果它是关于效率。

scope :never_contacted, -> { joins(:logs).where("logs.key IS NULL OR logs.key <> ?", "contacted").uniq } 
+0

谢谢,这看起来很完美。我仍然觉得奇怪,“无日志”和“只有其他日志”的情况必须分开处理。猜猜SQL不是专为负面查找而设计的。 – Epigene

+0

这也不会削减它。 “logs.key IS NULL”仅返回具有没有密钥的日志的用户,而不是没有日志的用户。如果只是有一种方法可以将这个答案与Simone Carletti的答案结合起来。 – Epigene

相关问题