如果我有一个带lambda的作用域,它接受一个参数,这取决于参数的值,我可能知道不会有任何匹配,但我仍然想返回一个关系,而不是一个空数组:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
我真正想要的是一个“none”方法,与“all”相反,它返回一个仍然可以被链接的关系,但会导致查询短路。
如果我有一个带lambda的作用域,它接受一个参数,这取决于参数的值,我可能知道不会有任何匹配,但我仍然想返回一个关系,而不是一个空数组:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
我真正想要的是一个“none”方法,与“all”相反,它返回一个仍然可以被链接的关系,但会导致查询短路。
当前回答
也有变体,但所有这些都是向db发出请求
where('false')
where('null')
其他回答
这是可能的,所以
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : User.none }
http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
如果我说错了,请指正。
scope :none, limit(0)
是一个危险的解决方案,因为您的瞄准镜可能会被链接。
User.none.first
将返回第一个用户。使用起来更安全
scope :none, where('1 = 0')
比起其他选择,我更喜欢这种方式:
scope :none, limit(0)
导致这样的结果:
scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }
你可以添加一个名为"none"的作用域:
scope :none, where(:id => nil).where("id IS NOT ?", nil)
这将给你一个空的ActiveRecord::Relation
你也可以将它添加到初始化器中的ActiveRecord::Base(如果你想):
class ActiveRecord::Base
def self.none
where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
end
end
有很多方法可以得到类似的东西,但肯定不是保存在代码库中的最佳方法。我在重构时使用了scope:none,发现我需要保证短时间内ActiveRecord::Relation为空。
一个更可移植的解决方案,不需要“id”列,也不假设不会有id为0的行:
scope :none, where("1 = 0")
我还在寻找一种更“正确”的方式。