Подтвердить что ты не робот

В чем разница между использованием .exists? И .present? в Рубине?

Я хочу убедиться, что я использую их для правильного случая и хочу знать о любых тонкостях. Кажется, что они функционируют одинаково, чтобы проверить, определено ли поле объекта, когда я использую их через консоль, и в Интернете, когда я делал поиск в Google, не было много информации в Интернете. Спасибо!

4b9b3361

Ответ 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