Ruby-on-rails 使用 .exists? 和 .present 有什么区别?在红宝石?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13186722/
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-02 20:58:29  来源:igfitidea点击:

What is the difference between using .exists?, and .present? in Ruby?

ruby-on-railsruby

提问by perseverance

I want to make sure I'm using them for the correct occasion and want to know of any subtleties. They seem to function the same way, which is to check to see if a object field has been defined, when I use them via the console and there isn't a whole lot information online when I did a google search. Thanks!

我想确保我在正确的场合使用它们,并想知道任何微妙之处。它们似乎以相同的方式运行,即检查对象字段是否已定义,当我通过控制台使用它们时,当我进行谷歌搜索时,网上没有很多信息。谢谢!

回答by pje

To clarify: neither present?nor exists?are "pure" ruby—they're both from Rails-land.

澄清一下:既不是“纯”红宝石,present?也不exists?是“纯”红宝石——它们都来自 Rails-land。

present?

展示?

present?is an ActiveSupport extension to Object. It's usually used as a test for an object's general "falsiness". From the documentation:

present?是对Object. 它通常用于测试对象的一般“虚假”。从文档

An object is presentif it's not blank?. An object is blankif it's false, empty, or a whitespace string.

一个对象是present如果它不是blank?。一个目的是blank,如果是false空或空白字符串。

So, for example:

因此,例如:

[ "", " ", false, nil, [], {} ].any?(&:present?)
# => false

exists?

存在吗?

exists?is from ActiveResource. From its documentation:

exists?来自 ActiveResource。从它的文档

Asserts the existence of a resource, returning true if the resource is found.

断言资源的存在,如果找到资源则返回 true。

Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
Note.exists?(1) # => true

回答by avital

The big difference between the two methods, is that when you call present?it initializes ActiveRecord for each record found(!), while exists?does not

这两种方法的最大区别在于,当您调用present?它时,会为找到的每个记录(!)初始化 ActiveRecord,而exists?不会

to show this I added after_initialize on User. it prints: 'You have initialized an object!'

为了显示这一点,我在用户上添加了 after_initialize。它打印:“你已经初始化了一个对象!”

User.where(name: 'mike').present?

User.where(name: 'mike').present?

User Load (8.1ms) SELECT "users".* FROM "users" WHERE "users"."name" =  ORDER BY users.id ASC  [["name", 'mike']]
You have initialized an object!
You have initialized an object!

User.exists?(name: 'mike')

User.exists?(名称:'迈克')

User Exists (2.4ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" =  ORDER BY users.id ASC LIMIT 1  [["name", 'mike']]

回答by sandre89

There is a huge difference in performance, and .present?can be up to 10x slower then .exists?depending on the relation you are checking.

性能存在巨大差异,根据您正在检查的关系,.present?速度可能会慢 10 倍.exists?

This articlebenchmarks .present?vs .any?vs .exists?and explains why they go from slower to faster, in this order.

本文.present?vs .any?vs.exists?进行了基准测试,并解释了为什么它们按此顺序从慢到快。

In a nutshell, .present?(900ms in the example) will load all records returned, .any?(100ms in the example) will use a SQLCount to see if it's > 0 and .exists?(1ms in the example) is the smart kid that uses SQL LIMIT 1 to just check if there's at least one record, without loading them all neither counting them all.

简而言之,.present?示例中为 900 毫秒)将加载返回的所有记录,.any?示例中为 100 毫秒)将使用 SQLCount 来查看它是否 > 0 并且.exists?示例中为 1毫秒)是使用 SQL LIMIT 1 的聪明孩子检查是否至少有一条记录,而不将它们全部加载,也不会将它们全部计算在内。

回答by buraksay

SELECT COUNT(*)would scan the records to get a count.

SELECT COUNT(*)将扫描记录以获得计数。

SELECT 1would stop after the first match, so their exec time would be very different.

SELECT 1会在第一场比赛后停止,所以他们的执行时间会大不相同。

回答by bigtex777

The SQL generated by the two are also different.

两者生成的SQL也不同。

present?:

present?

Thing.where(name: "Bob").present?
# => SELECT COUNT(*) FROM things WHERE things.name = "Bob";

exists?:

exists?

Thing.exists?(name: "Bob")
#?=> SELECT 1 AS one from things WHERE name ="Bob" limit 1;

They both seem to run the same speed, but may vary given your situation.

它们的运行速度似乎相同,但根据您的情况可能会有所不同。

回答by tkhuynh

You can avoid database query by using present?:

您可以使用present?以下方法避免数据库查询:

all_endorsements_11 = ArtworkEndorsement.where(user_id: 11)
ArtworkEndorsement Load (0.3ms)  SELECT "artwork_endorsements".* FROM "artwork_endorsements" WHERE "artwork_endorsements"."user_id" =   [["user_id", 11]]
all_endorsements_11.present?
=> true 
all_endorsements_11.exists?
ArtworkEndorsement Exists (0.4ms)  SELECT  1 AS one FROM "artwork_endorsements" WHERE "artwork_endorsements"."user_id" =  LIMIT 1  [["user_id", 11]]
=> true