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