Diferenças entre algum?"e" existe? em Ruby on Rails?

Em Ruby on Rails, parece haver dois métodos para verificar se uma coleção tem algum elemento nela.

ou seja, eles são ActiveRecord::FinderMethods' existe? e a relação é alguma?. Executando-os numa consulta genérica (Foo.first.bars.exists? e Foo.first.bars.any?) gerou SQL equivalente. Há alguma razão para usar um em vez do outro?

Author: Sebastian Palma, 2018-01-20

2 answers

#any e #exists? são animais muito diferentes, mas questionam da mesma forma.

Principalmente, #any? aceita um bloco - e com este bloco recupera os registos na relação, chama #to_a, chama o bloco, e depois atinge-o com Enumerable#any?. Sem um bloco, é o equivalente a !empty? e conta os registos da relação.

#exists? Sempre questiona a base de dados e nunca se baseia em registos pré-carregados, e define um limite de 1. É muito mais performant vs #any?. #exists? também aceita uma opção param como condições para aplicar como você pode ver nos documentos.

 1
Author: Josh Brody, 2018-01-19 22:42:57

A utilização de ActiveRecord#any? é reduzida ao longo de ActiveRecord#exists?. Com algum? você pode verificar, no caso de passar um bloco, se certos elementos desse array correspondem aos critérios. Semelhante à Enumerable#any? mas não os confunda.

O ActiveRecord#any? implementa a Enumerable#any? dentro da lógica da sua definição , convertendo a relação acedida a um array no caso de um bloco ter sido passado para ele e produz e acede aos parâmetros do bloco para implementar de uma forma "manual " um" Ruby " any? metodo.

O outro útil adicionado pretende devolver a negação do vazio? aplicado à relação. É por isso que se pode verificar de ambos os modos se um modelo tem ou não registos, como:

User.count # 0
User.any?  # false
# SELECT  1 AS one FROM "users" LIMIT ?  [["LIMIT", 1]]
User.exists? # false
# SELECT  1 AS one FROM "users" LIMIT ?  [["LIMIT", 1]]

Você também pode verificar No " qualquer?"way, if some record attribute has a specific value:

Foo.any? { |foo| foo.title == 'foo' } # SELECT "posts".* FROM "posts"

Ou salvar a "eficiência" usando existe? e melhore sua consulta e linhas de código:

Foo.exists?('foo') # SELECT  1 AS one FROM "posts" WHERE "posts"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]

ActiveRecord#exists? oferece muitas implementações e se destina a trabalhar em um nível SQL, ao invés de any?, isso de qualquer maneira irá converter a relação com que você está trabalhando em um array se você não passar um bloco.

 1
Author: Sebastian Palma, 2018-01-19 23:15:47