Ruby-on-rails 如何返回一个空的 ActiveRecord 关系?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4877931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:17:27  来源:igfitidea点击:

How to return an empty ActiveRecord relation?

ruby-on-railsactiverecordrelation

提问by dzajic

If I have a scope with a lambda and it takes an argument, depending on the value of the argument, I might know that there will not be any matches, but I still want to return a relation, not an empty array:

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

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

What I really want is a "none" method, the opposite of "all", that returns a relation that can still be chained, but results in the query being short-circuited.

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

回答by steveh7

There is a now a "correct" mechanism in Rails 4:

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

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

回答by steveh7

A more portable solution that doesn't require an "id" column and doesn't assume there won't be a row with an id of 0:

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

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

I'm still looking for a more "correct" way.

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

回答by Nathan Long

Coming in Rails 4

加入 Rails 4

In Rails 4, a chainable ActiveRecord::NullRelationwill be returned from calls like Post.none.

在 Rails 4 中,ActiveRecord::NullRelationPost.none.

Neither it, nor chained methods, will generate queries to the database.

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

According to the comments:

根据评论:

The returned ActiveRecord::NullRelation inherits from Relation and implements the Null Object pattern. It is an object with defined null behavior and always returns an empty array of records without quering the database.

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

See the source code.

请参阅源代码

回答by Brandon

You can add a scope called "none":

您可以添加一个名为“none”的范围:

scope :none, where(:id => nil).where("id IS NOT ?", nil)

That will give you an empty ActiveRecord::Relation

这会给你一个空的 ActiveRecord::Relation

You could also add it to ActiveRecord::Base in an initializer (if you want):

您还可以将其添加到 ActiveRecord::Base 中的初始值设定项(如果需要):

class ActiveRecord::Base
 def self.none
   where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
 end
end

Plenty of ways to get something like this, but certainly not the best thing to keep in a code base. I have used the scope :none when refactoring and finding that I need to guarantee an empty ActiveRecord::Relation for a short time.

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

回答by bbrinck

scope :none, limit(0)

Is a dangerous solution because your scope might be chained upon.

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

User.none.first

无用户优先

will return the first user. It's safer to use

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

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

回答by Alex

I think I prefer the way this looks to the other options:

我想我更喜欢这种方式而不是其他选项:

scope :none, limit(0)

Leading to something like this:

导致这样的事情:

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

回答by Pan Thomakos

Use scoped:

使用范围:

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

But, you can also simplify your code with:

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

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

If you want an empty result, use this (remove the if condition):

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

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

回答by ilgam

It is possible and so that's:

这是可能的,所以这是:

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

http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none

Correct me if I'm wrong.

如果我错了纠正我。

回答by fmnoise

There are also variants, but all of these are making request to db

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

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