Qual é a diferença entre usar.existe?, e.presente? em Ruby?

Quero ter a certeza que os estou a usar para a ocasião certa e quero saber de subtilezas. Eles parecem funcionar da mesma forma, que é verificar se um campo objeto foi definido, quando eu usá-los através do console e não há muita informação online quando eu fiz uma pesquisa no google. Obrigado!

Author: perseverance, 2012-11-02

6 answers

Para esclarecer: nem present? nem exists? são rubis "puros"-são ambos de Rails-land. Presente?

present? is an ActiveSupport extension to Object. Geralmente é usado como um teste para a "falsidade"geral de um objeto. Da documentação:

Um objecto é present Se não for blank?. Um objecto é blank se for false, vazio, ou um texto Em Branco.

Então, por exemplo:

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

exists? é de ActiveResource. Da sua documentação:

Afirma a existência de um recurso, retornando verdadeiro se o recurso for encontrado.

Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
Note.exists?(1) # => true
 55
Author: pje, 2016-10-02 03:27:51

A grande diferença entre os dois métodos, é que quando você chama present? ele inicializa o ActiveRecord para cada registro encontrado (!), enquanto exists? não

Para mostrar isto, adicionei a seguir a_ inicializar no utilizador. ele imprime: 'você inicializou um objeto!'

Utilizador.em que (nome: "mike").presente?

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!

Utilizador.existe?(nome: 'mike')

User Exists (2.4ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC LIMIT 1  [["name", 'mike']]
 13
Author: avital, 2015-05-12 13:53:01

Existe uma enorme diferença no desempenho, e {[[0]} pode ser até 10x mais lento do que .exists? dependendo da relação que está a verificar.

Este artigo define parâmetros de referência .present? vs .any? vs .exists? e explica por que passam de mais lento para mais rápido, por esta ordem.

Em poucas palavras, .present? (900ms no exemplo) irá carregar todos os registros retornados, .any? (100ms no exemplo) vai usar um SQLCount para ver se é > 0 e .exists? (1ms no exemplo) é o garoto inteligente que usa o limite SQL 1 para apenas verificar se há pelo menos um registro, sem carregá-los todos nem contá-los todos.

 5
Author: sandre89, 2017-05-04 05:20:55

SELECT COUNT(*) analisava os registos para fazer uma contagem.

SELECT 1 pararia depois da primeira partida, para que o tempo do exec fosse muito diferente.

 5
Author: buraksay, 2017-06-05 03:05:47

O SQL gerado pelos dois também é diferente.

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;
Ambos parecem correr à mesma velocidade, mas podem variar, dada a sua situação.
 2
Author: bigtex777, 2017-06-05 03:06:38

Pode evitar a pesquisa na base de dados usando 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 
 -1
Author: tkhuynh, 2017-06-05 03:05:29