J3R*_*3RN 9 ruby activerecord ruby-on-rails ruby-on-rails-4
在 Ruby on Rails 中,似乎有两种方法可以检查集合中是否包含任何元素。
也就是说,它们是ActiveRecord::FinderMethods 的存在吗?和ActiveRecord::Relation 有什么关系?. 在通用查询 (Foo.first.bars.exists?和Foo.first.bars.any?) 中运行这些会生成等效的 SQL。有什么理由使用一个而不是另一个吗?
Jos*_*ody 12
#any并且#exists?是非常不同的野兽,但查询相似。
主要是#any?接受一个块——它用这个块检索关系中的记录,调用#to_a,调用块,然后用 命中它Enumerable#any?。没有块,它相当于!empty?并计算关系的记录。
#exists? 始终查询数据库,从不依赖预加载的记录,并将 LIMIT 设置为 1。与#any?. #exists?还接受一个选项参数作为应用条件,如您在文档中所见。
的使用量ActiveRecord#any?减少超过ActiveRecord#exists?. 与任何?在传递块的情况下,您可以检查该数组中的某些元素是否符合条件。与 类似,Enumerable#any?但不要混淆它们。
通过将块已传递给它的情况下访问的关系转换为数组,并生成和访问块参数,以“手工制作”的方式实现“Ruby”方法,实现其定义的内部ActiveRecord#any?逻辑。Enumerable#any?any?
添加的方便的 else 旨在返回空的否定?应用于关系。这就是为什么您可以通过两种方式检查模型中是否有记录,例如:
User.count # 0
User.any? # false
# SELECT 1 AS one FROM "users" LIMIT ? [["LIMIT", 1]]
User.exists? # false
# SELECT 1 AS one FROM "users" LIMIT ? [["LIMIT", 1]]
Run Code Online (Sandbox Code Playgroud)
您还可以检查“有吗?” 方式,如果某些记录属性具有特定值:
Foo.any? { |foo| foo.title == 'foo' } # SELECT "posts".* FROM "posts"
Run Code Online (Sandbox Code Playgroud)
或者通过使用exists来节省“效率”?并改进您的查询和代码行:
Foo.exists?(title: 'foo') # SELECT 1 AS one FROM "posts" WHERE "posts"."title" = ? LIMIT ? [["title", "foo"], ["LIMIT", 1]]
Run Code Online (Sandbox Code Playgroud)
ActiveRecord#exists?提供了许多实现,并且旨在在 SQL 级别工作,而不是any?在 SQL 级别工作,如果您不传递块,无论如何都会将您在数组中使用的关系转换为关系。