Verifique se existe registro do controlador no Rails


90

No meu aplicativo, um usuário pode criar um negócio. Quando eles acionam a indexação no meu BusinessesController, quero verificar se um negócio está relacionado a current_user.id:

  • Se sim: mostre o negócio.
  • Se não: redirecione para a newação.

Eu estava tentando usar isto:

if Business.where(:user_id => current_user.id) == nil
  # no business found
end

Mas sempre retorna verdadeiro mesmo quando o negócio não existe ...

Como posso testar se existe um registro em meu banco de dados?


1
O uso de whereretornará um array vazio se não houver registros. E []não é igualnil
mind.blank

Que tal apenas um unless Business.find_by_user_id(current_user.id)?
Hengjie

Respostas:


228

Por que seu código não funciona?

O wheremétodo retorna um objeto ActiveRecord :: Relation (age como um array que contém os resultados de where), pode estar vazio, mas nunca estaránil .

Business.where(id: -1) 
 #=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
 #=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
 #=> returns true

Como testar se existe pelo menos um registro?

Opção 1: usando.exists?

if Business.exists?(user_id: current_user.id)
  # same as Business.where(user_id: current_user.id).exists?
  # ...
else
  # ...
end

Opção 2: usando .present?(ou .blank?o oposto de .present?)

if Business.where(:user_id => current_user.id).present?
  # less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
  # ...
end

Opção 3: atribuição de variável na instrução if

if business = Business.where(:user_id => current_user.id).first
  business.do_some_stuff
else
  # do something else
end

Esta opção pode ser considerada um cheiro de código por alguns linters (Rubocop por exemplo).

Opção 3b: Atribuição de variável

business = Business.where(user_id: current_user.id).first
if business
  # ...
else
  # ...
end

Você também pode usar em .find_by_user_id(current_user.id)vez de.where(...).first


Melhor opção:

  • Se você não usar o Business(s) objeto (s): Opção 1
  • Se você precisar usar o Business(s) objeto (s): Opção 3

Isso não pareceu funcionar. Ele continua passando nesse teste e carregando o html de índice como com o teste == nil (então estou recebendo um erro: método indefinido `nome 'para nil: NilClass).

Experimente primeiro antes de ligar para o presente
MrYoshiji

Tenho o mesmo problema

Oh, isso é minha culpa, eu estava confuso, você precisa testar comblank?
MrYoshiji

Obrigado que funcionou! Eu não deveria ter percebido esse erro. Você poderia me dizer por que a verificação == nil não funcionou?

28

Neste caso, gosto de usar o exists?método fornecido pelo ActiveRecord:

Business.exists? user_id: current_user.id

Existe? com OR possível?
Imran Ahmad

5

com 'existe?':

Business.exists? user_id: current_user.id #=> 1 or nil

com qualquer?':

Business.where(:user_id => current_user.id).any? #=> true or false

Se você usar algo com .where, certifique-se de evitar problemas com escopos e usar melhor .unscoped

Business.unscoped.where(:user_id => current_user.id).any?

Melhor usar Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? para evitar carga desnecessária de relações para o objeto que você está verificando.
Juanin

1

ActiveRecord # onde retornará um objeto ActiveRecord :: Relation (que nunca será nulo). Tente usar .empty? na relação para testar se ele retornará algum registro.


1

Quando você ligar, Business.where(:user_id => current_user.id)você obterá um array. Este Array pode não ter objetos ou um ou mais objetos, mas não será nulo. Portanto, a verificação == nil nunca será verdadeira.

Você pode tentar o seguinte:

if Business.where(:user_id => current_user.id).count == 0

Portanto, você verifica o número de elementos na matriz e os compara a zero.

ou você pode tentar:

if Business.find_by_user_id(current_user.id).nil?

isso retornará um ou nulo.


1
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end

0

Eu faria isso dessa forma se você precisasse de uma variável de instância do objeto para trabalhar:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.