dan*_*des 6 sql activerecord ruby-on-rails arel
是否有where使用ActiveRecord / ARel 否定整个表达式的简单方法?看起来where.not(),当给定参数散列时,分别对每个表达式求反,而不是使用单个SQL对整个事物求反NOT。
Thing.where.not(attribute1: [1,2], attribute2: [3,4], attribute3: [5,6])
select * from things where attribute1 NOT IN (1,2) AND attribute2 NOT IN (3,4) AND attribute3 NOT IN (5,6)
这不是我要尝试做的。我想用单个否定整个where子句NOT。
select * from things where NOT(attribute1 IN (1,2) AND attribute2 IN (3,4) AND attribute3 IN (5,6))
用布尔符号表示,Rails似乎更喜欢否定WHERE子句的每个组件,如下所示:
!(a) && !(b) && !(c)
但是我想否定整个表达式:
! [ (a) && (b) && (c) ]
使用DeMorgan定律,我可以将查询编写为!a || !b || !c,但这将导致代码相当长且难看(对于Rails 5和Rails来说or,代码的长度较短,但仍然很丑)。我希望使用ActiveRecord或ARel缺少一些语法糖?
我正在编写一个Ransack等式作用域(例如_eq)来搜索条件及其相反的条件。
scope :can_find_things_eq, ->(boolean = true) {
case boolean
when true, 'true'
where(conditions_for_things)
when false, 'false'
where.not(conditions_for_things)
end
}
def self.ransackable_scopes(_auth_object = nil)
%i[can_find_things_eq]
end
Run Code Online (Sandbox Code Playgroud)
如果我使用上面的Rails 5建议和我的示例开始,我的求反查询就可以工作了……但是代码又长又丑。
where.not(attribute1: [1,2]).or(where.not(attribute2:
[3,4)).or(where.not(attribute3: [5,6))
Run Code Online (Sandbox Code Playgroud)
链接Ors和WhereNots可以工作,但是可读性不强。where除了必须使用DeMorgan定律手动/逻辑否定之外,还有其他更好的方法可以否定它吗?
谢谢!