如何返回空的ActiveRecord关系?

问题描述 投票:0回答:10

如果我有一个带有 lambda 的作用域并且它需要一个参数,根据参数的值,我可能知道不会有任何匹配项,但我仍然想返回一个关系,而不是一个空数组:

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

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

ruby-on-rails activerecord relation
10个回答
566
投票

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

>> Model.none 
=> #<ActiveRecord::Relation []>

76
投票

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

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

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


46
投票

Rails 4 即将到来

在 Rails 4 中,可链接的

ActiveRecord::NullRelation
将从像
Post.none
这样的调用中返回。

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

根据评论:

返回的ActiveRecord::NullRelation继承自 关系并实现空对象模式。它是一个对象 定义空行为并始终返回空记录数组 无需查询数据库。

查看源代码


43
投票

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


26
投票
scope :none, limit(0)

这是一个危险的解决方案,因为你的范围可能会被束缚。

用户.none.first

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

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

15
投票

我想我更喜欢它的外观而不是其他选项:

scope :none, limit(0)

导致这样的事情:

scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }

3
投票

使用范围:

范围:for_users,lambda { |用户|用户.有吗? ? where("user_id IN (?)", users.map(&:id).join(',')) : 范围 }

但是,您也可以使用以下方法简化代码:

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

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

范围:for_users,lambda { |用户|其中(:user_id => users.map(&:id)) }

2
投票

还有变体,但所有这些都向数据库发出请求

where('false')
where('null')

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

如果我错了请纠正我。


0
投票

查看文档

(从 Rails 4.0.2 开始) 在任何

.none
上调用
ActiveRecord::Relation
将返回具有零记录的可链接关系。

© www.soinside.com 2019 - 2024. All rights reserved.