Verifique si existe un registro del controlador en Rails

91

En mi aplicación, un usuario puede crear una empresa. Cuando desencadenan la indexacción en mi BusinessesControllerquiero comprobar si un negocio está relacionado con current_user.id:

  • En caso afirmativo: muestre el negocio.
  • Si no: redirige a la newacción.

Estaba tratando de usar esto:

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

Pero siempre vuelve verdadero incluso cuando el negocio no existe ...

¿Cómo puedo probar si existe un registro en mi base de datos?

MrYoshiji
fuente
1
El uso wheredevolverá una matriz vacía si no hay registros. Y []no es igualnil
mind.blank
¿Qué tal solo un unless Business.find_by_user_id(current_user.id)?
Hengjie
posible duplicado de Comprobar si la búsqueda de ActiveRecord devuelve un resultado
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

231

¿Por qué tu código no funciona?

El wheremétodo devuelve un objeto ActiveRecord :: Relation (actúa como una matriz que contiene los resultados del where), puede estar vacío pero nunca lo 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

¿Cómo probar si existe al menos un registro?

Opción 1: usar.exists?

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

Opción 2: Usar .present?(o .blank?lo contrario 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

Opción 3: Asignación de variable en la instrucción if

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

Esta opción puede ser considerada un olor a código por algunos linters (Rubocop por ejemplo).

Opción 3b: asignación de variable

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

También puede usar en .find_by_user_id(current_user.id)lugar de.where(...).first


Mejor opción:

  • Si no usa el Business(los) objeto (s): Opción 1
  • Si necesita usar el Businessobjeto (s): Opción 3
MrYoshiji
fuente
Eso no pareció funcionar. Sigue pasando esa prueba y cargando el índice html como con la prueba == nil (así que obtengo un error: método indefinido `nombre 'para nil: NilClass).
Pruebe primero antes de llamar al presente
MrYoshiji
Tengo el mismo problema
Oh, eso es mi culpa, estaba confundido, necesitas probar conblank?
MrYoshiji
¡Gracias que funcionó! No debería haber notado ese error. ¿Podría decirme por qué no funcionó la comprobación == nil?
29

En este caso, me gusta usar el exists?método proporcionado por ActiveRecord:

Business.exists? user_id: current_user.id
Hamed
fuente
¿Existe? con O posible?
Imran Ahmad
5

con 'existe?':

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

¿con cualquier?':

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

Si usa algo con .where, asegúrese de evitar problemas con los visores y utilice mejor .

Business.unscoped.where(:user_id => current_user.id).any?
usuario2427993
fuente
Es mejor usar Business.unscoped.where (: user_id => current_user.id) .pluck (: id) .any? para evitar una carga innecesaria de relaciones para el objeto que está comprobando.
Juanin
1

ActiveRecord # donde devolverá un objeto ActiveRecord :: Relation (que nunca será nulo). ¿Intenta usar .empty? en la relación para probar si devolverá algún registro.

Puhlze
fuente
1

Cuando llame Business.where(:user_id => current_user.id), obtendrá una matriz. Esta matriz puede no tener objetos o tener uno o muchos objetos, pero no será nula. Por tanto, la comprobación == nil nunca será verdadera.

Puedes probar lo siguiente:

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

Entonces, verifica el número de elementos en la matriz y los compara con cero.

o puedes probar:

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

esto devolverá uno o nulo.

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

Lo haría de esta manera si necesitara una variable de instancia del objeto para trabajar:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
user3633260
fuente