Qual é a diferença entre usar.existe?, e.presente? em Ruby?
6 answers
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 forblank?
. Um objecto éblank
se forfalse
, 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
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']]
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.
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.
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.
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