273

如果我有一个带有 lambda 的范围并且它需要一个参数,这取决于参数的值,我可能知道不会有任何匹配项,但我仍然想返回一个关系,而不是一个空数组:

scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }

我真正想要的是一个“无”方法,与“全部”相反,它返回一个仍然可以链接的关系,但会导致查询短路。

4

9 回答 9

532

Rails 4 现在有一个“正确”的机制:

>> Model.none 
=> #<ActiveRecord::Relation []>
于 2012-04-03T20:39:48.367 回答
76

一种更便携的解决方案,它不需要“id”列并且不假设不会有 id 为 0 的行:

scope :none, where("1 = 0")

我仍在寻找更“正确”的方式。

于 2011-03-16T04:12:59.313 回答
46

加入 Rails 4

在 Rails 4 中,一个可链式ActiveRecord::NullRelation调用将从像Post.none.

它和链式方法都不会生成对数据库的查询。

根据评论:

返回的 ActiveRecord::NullRelation 继承自 Relation 并实现 Null Object 模式。它是一个定义了空行为的对象,并且总是返回一个空的记录数组而不查询数据库。

请参阅源代码

于 2012-10-23T19:18:01.330 回答
42

您可以添加一个名为“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

有很多方法可以获得这样的东西,但肯定不是保存在代码库中的最佳方法。我在重构时使用了范围:none,发现我需要在短时间内保证一个空的 ActiveRecord::Relation。

于 2011-02-21T06:44:01.507 回答
26
scope :none, limit(0)

是一个危险的解决方案,因为您的范围可能会受到束缚。

User.none.first

将返回第一个用户。使用起来更安全

scope :none, where('1 = 0')
于 2012-04-12T16:00:47.613 回答
15

我认为我更喜欢其他选项的外观:

scope :none, limit(0)

导致这样的事情:

scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }
于 2011-06-22T13:59:31.107 回答
3

使用范围:

范围 :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : scoped }

但是,您还可以通过以下方式简化代码:

范围 :for_users, lambda { |users| where(:user_id => users.map(&:id)) 如果 users.any?}

如果您想要一个空结果,请使用它(删除 if 条件):

范围 :for_users, lambda { |users| 其中(:user_id => users.map(&:id)) }
于 2011-02-02T18:01:18.320 回答
2

也有变种,但所有这些都在向 db 发出请求

where('false')
where('null')
于 2014-10-17T12:34:21.360 回答
2

这是可能的,所以这是:

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

如我错了请纠正我。

于 2015-05-13T14:03:50.707 回答