使用.exists?和.present有什么区别?在Ruby?

时间:2012-11-01 22:51:57

标签: ruby-on-rails ruby

我想确保我在正确的场合使用它们,并想知道任何细微之处。它们似乎以相同的方式起作用,即检查是否已经定义了一个对象字段,当我通过控制台使用它们时,当我进行谷歌搜索时,并没有在线提供大量信息。谢谢!

6 个答案:

答案 0 :(得分:65)

澄清:present?exists?都不是“纯粹的”红宝石 - 他们都来自Rails-land。

本?

present?Object的ActiveSupport扩展程序。它通常用作对象的一般“虚假”的测试。来自the documentation

  

如果某个对象不是present,则该对象为blank?。对象是blank,如果它是false,为空或者是空白字符串。

所以,例如:

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

存在?

exists?来自ActiveResource。来自its documentation

  

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

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

答案 1 :(得分:20)

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

为了表明这一点,我在User上添加了after_initialize。它打印:'你已经初始化了一个对象!'

  

User.where(姓名:'迈克')。现在?

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

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

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

答案 2 :(得分:10)

性能存在巨大差异,.present?可能比.exists?慢10倍,具体取决于您检查的关系。

This article基准.present? vs .any? vs .exists?并解释了为什么它们按此顺序从慢到快。

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

答案 3 :(得分:6)

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

SELECT 1会在第一场比赛后停止,所以他们的执行时间会有很大差异。

答案 4 :(得分:2)

两者生成的SQL也不同。

present?

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

exists?

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

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

答案 5 :(得分:-2)

您可以使用present?

来避免数据库查询
all_endorsements_11 = ArtworkEndorsement.where(user_id: 11)
ArtworkEndorsement Load (0.3ms)  SELECT "artwork_endorsements".* FROM "artwork_endorsements" WHERE "artwork_endorsements"."user_id" = $1  [["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" = $1 LIMIT 1  [["user_id", 11]]
=> true