如何返回一个空的ActiveRecord关系?

时间:2011-02-02 17:50:30

标签: ruby-on-rails activerecord relation

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

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

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

9 个答案:

答案 0 :(得分:433)

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

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

答案 1 :(得分:75)

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

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

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

答案 2 :(得分:43)

进入Rails 4

在Rails 4中,可以通过ActiveRecord::NullRelation之类的调用返回可链接的Post.none

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

根据评论:

  

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

请参阅source code

答案 3 :(得分: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

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

答案 4 :(得分:24)

scope :none, limit(0)

是一种危险的解决方案,因为您的范围可能会受到限制。

User.none.first

将返回第一个用户。使用

更安全
scope :none, where('1 = 0')

答案 5 :(得分:14)

我认为我更喜欢这种方式与其他选项的对比:

scope :none, limit(0)

导致类似这样的事情:

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

答案 6 :(得分:3)

使用范围:

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

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

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

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

scope :for_users, lambda { |users| where(:user_id => users.map(&:id)) }

答案 7 :(得分:1)

还有变体,但所有这些都向db

发出请求
where('false')
where('null')

答案 8 :(得分:1)

这是可能的,所以

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

如果我错了,请纠正我。