Я хочу убедиться, что я использую их для правильного случая и хочу знать о любых тонкостях. Кажется, что они функционируют одинаково, чтобы проверить, определено ли поле объекта, когда я использую их через консоль, и в Интернете, когда я делал поиск в Google, не было много информации в Интернете. Спасибо!
В чем разница между использованием .exists? И .present? в Рубине?
Ответ 1
Чтобы уточнить: ни present?
, ни exists?
не являются "чистыми" рубинами - они оба из Rails-land.
присутствует
present?
- расширение ActiveSupport для Object
. Он обычно используется как тест для общего "фальшивости" объекта. Из документация:
Объект
present
, если его неblank?
. Объектblank
, если егоfalse
, пустой или строка пробела.
Итак, например:
[ "", " ", false, nil, [], {} ].any?(&:present?)
# => false
существует?
exists?
- из ActiveResource. Из его документации:
Указывает на существование ресурса, возвращая true, если ресурс найден.
Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
Note.exists?(1) # => true
Ответ 2
Большая разница между этими двумя методами заключается в том, что при вызове present?
он инициализирует ActiveRecord для каждой найденной записи (!), а exists?
не
чтобы показать это, я добавил after_initialize в User. он печатает: "Вы инициализировали объект!"
User.where(name: 'mike'). present?
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? (name: 'mike')
User Exists (2.4ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC LIMIT 1 [["name", 'mike']]
Ответ 3
SELECT COUNT(*)
будет сканировать записи, чтобы получить счет.
SELECT 1
остановится после первого совпадения, поэтому время их выполнения будет совсем другим.
Ответ 4
Существует огромная разница в производительности, а .present?
может быть до 10 раз медленнее, чем .exists?
в зависимости от того, какое отношение вы проверяете.
Эта статья содержит тесты .present?
vs .any?
vs .exists?
и объясняет, почему они идут от более медленного к более быстрому, в этом порядке,
В двух словах .present?
(900 мс в примере) загрузит все возвращенные записи, .any?
( 100 мс в примере) будет использовать SQLCount для см., если он > 0 и .exists?
( 1 мс в примере) - умный парень, который использует SQL LIMIT 1, чтобы просто проверить, есть ли хотя бы одна запись, не загружая их всех, не подсчитывая их всех.
Ответ 5
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;
Оба они, похоже, работают с одинаковой скоростью, но могут варьироваться в зависимости от вашей ситуации.
Ответ 6
Вы можете избежать запроса базы данных, используя 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