否定ActiveRecord查询范围

我的模型范围略微复杂

class Contact  { where(inactive: false) } scope :groups, -> { where(contact_type: 2308) } scope :group_search, -> (query) do active.groups.where("last_name LIKE '%' + ? + '%'", query) end end 

出于测试目的,我想确保group_search 返回的所有Contacts都被排除在正确的原因之外。

但要获得该列表,我必须加载

 Contact.all - Contact.group_search('query') 

它运行两个查询,返回一个Array而不是一个Relation ,并且比我想要的慢。

由于我正在测试group_search范围,因此编写另一个负面范围会破坏这一点。 我宁愿做一些像:

 Contact.merge.not(Contact.group_search('query')) 

生成以下SQL查询:

 SELECT * FROM contacts WHERE NOT (contact_type = 2308 AND inactive = 0 AND last_name LIKE '%' + ? + '%') 

有没有办法做到这一点?

我认为你所寻找的是否定范围,你可以尝试以下方法:

 conditions = Contact.group_search('query').where_values @contacts = Contact.where.not(conditions.reduce(:and)) 

要使此解决方案在Rails 4.x中工作,您应该在作用域中提供值作为数组:

 scope :groups, -> { where(contact_type: [2308]) } 

我也发现了一个简洁的通用实现来否定范围 ,你也可能会发现它很有趣。