Comprobando si una variable no es nula y no es cero en rubí

271

Estoy usando el siguiente código para verificar si una variable no es nula y no es cero

if(discount != nil && discount != 0) 
  ...
end

¿Hay una mejor manera de hacer esto?

hectorsq
fuente
1
Probablemente porque es una copia exacta de stackoverflow.com/questions/209495/… .
David Nehme
1
¿Qué debe hacer si discountes falso?
Andrew Grimm
1
Creo que discount.in? [0, nil]la forma más limpia posible
intmarinoreturn0

Respuestas:

428
a menos que discount.nil? || descuento == 0
  # ...
final
Dejan Simic
fuente
31
Use 'o' en lugar de ||
Orion Edwards
93
@ orion-edwards ¿por qué?
NARKOZ
39
Usar 'o' es peligroso. 'o' tiene una presencia de operador menor que '=', por lo que lo siguiente tiene un comportamiento inesperado: a = falso o verdadero #a es falso después de esta declaración
Tom G
20
@xiy actualmente la guía recomienda fingir o y y no existen (|| es eso o && y?)
usuario3125280
67
Soportes actuales de la "Guía de estilo Ruby" The and and or keywords are banned. It's just not worth it. Always use && and || instead.. Y es correcto, por razones de David y Tom.
Andre Figueiredo
40
class Object
  def nil_zero?
    self.nil? || self == 0
  end
end

# which lets you do
nil.nil_zero? # returns true
0.nil_zero?   # returns true
1.nil_zero?   # returns false
"a".nil_zero? # returns false

unless discount.nil_zero?
  # do stuff...
end

Tenga cuidado con los descargos de responsabilidad habituales ... gran poder / responsabilidad, parches de mono que conducen al lado oscuro, etc.

madlep
fuente
28

ok, después de 5 años han pasado ...

if discount.try :nonzero?
  ...
end

Es importante tener en cuenta que tryestá definido en la gema ActiveSupport, por lo que no está disponible en ruby ​​simple.

reescrito
fuente
77
Tenga en cuenta que esta es una respuesta específica de rieles . El rubí de vainilla no tiene un trymétodo.
Tom Lord
Correcto. Aunque se parece más a ActiveSupport específico, que es una dependencia mucho más ligera y ampliamente utilizada que los rieles completos. De todos modos, ahora la respuesta de @ ndn es la correcta.
reescrito el
Editado para usar navegación segura
reescrito el
1
La respuesta ahora duplica stackoverflow.com/a/34819818/1954610 ... Creo que tiene valor dejarlo como trypara mostrar la opción alternativa (¡esta es la razón por la que se votó en primer lugar!), Siempre que sea claro El lector que ActiveSupportno es vainilla rubí.
Tom Lord
Punto tomado, la respuesta rodada hacia atrás.
reescrito el
27
a menos que [nil, 0] .include? (descuento) 
  # ...
final
Dejan Simic
fuente
13
¿Hermoso? Si. ¿Legible? Realmente no.
El Ninja Trepador
1
Encuentro esto perfectamente legible, y preferiría que fuera una nueva clase. Bien hecho.
colincr
El enfoque más rubí de manejar dos condiciones.
Yugendran
23

Desde Ruby 2.3.0 en adelante, puede combinar el operador de navegación segura ( &.) con Numeric#nonzero?. &.devuelve nilsi la instancia fue nily nonzero?- si el número fue 0:

if discount&.nonzero?
  # ...
end

O postfix:

do_something if discount&.nonzero?
ndnenkov
fuente
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Esto no es seguro de usar en objetos arbitrarios.
Tom Lord
2
@TomLord, como se indicó en el comentario anterior, esto no estaba destinado a trabajar con objetos arbitrarios. En cambio, se refiere al caso cuando tiene algo que sabe que debería ser un número, pero también podría serlo nil.
ndnenkov
Dejaría ese hecho claro en la respuesta, en lugar de que alguien lea esto y no vea el descargo de responsabilidad en los comentarios.
Tom Lord
@TomLord, se indica en la respuesta " nonzero?- si el número era 0" . Además, la necesidad de verificar si un objeto completamente arbitrario 0surge extremadamente rara vez en comparación con eso para verificar un número que puede o no ser nil. Por lo tanto, está casi implícito. Incluso si alguien de alguna manera asume lo contrario, comprenderá instantáneamente lo que está sucediendo cuando intente ejecutarlo.
ndnenkov
17
if (discount||0) != 0
  #...
end
Raimonds Simanovskis
fuente
Esta es mi respuesta favorita
Wilson Freitas
15

Podrías hacer esto:

if (!discount.nil? && !discount.zero?)

El orden es importante aquí, porque si discountes así nil, entonces no tendrá un zero?método. discount.zero?Sin embargo, la evaluación de cortocircuito de Ruby debería evitar que intente evaluar , si discountes así nil.

Jeremy Ruten
fuente
11

¿Puede convertir su fila vacía a un valor entero y verificar cero?

"".to_i.zero? => true
nil.to_i.zero? => true
oivoodoo
fuente
cuidado: 0.1.to_i == 0
Simon B.
3
if discount and discount != 0
  ..
end

actualización, lo hará falseparadiscount = false

rubyprince
fuente
2

Puede aprovechar el método NilClassproporcionado #to_i, que devolverá cero para los nilvalores:

unless discount.to_i.zero?
  # Code here
end

Si discountpueden ser números fraccionarios, puede usarlos #to_fpara evitar que el número se redondee a cero.

Dave GW
fuente
¿No es esto lo mismo que la respuesta de @ oivoodo?
Cary Swoveland
No funciona para objetos arbitrarios . "".to_i == "foo".to_i == "0".to_i == 0. Su método hará todo tipo de coacciones de tipo no intencionadas. También fallará con un NoMethodErrorif discountque no responde to_i.
Tom Lord
2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Si pasamos "", ¿devolverá falso mientras está en blanco? devuelve verdadero Igual es el caso cuando data = false blank? devuelve verdadero para nil, falso, vacío o una cadena de espacio en blanco. Entonces, ¿es mejor usar en blanco? método para evitar una cadena vacía también.

Saroj
fuente
1
blank?es un método específico para rieles y no está disponible en vainilla rubí.
Tom Lord
¡¡Estás en lo correcto!! Pensé que esto está relacionado con la etiqueta "ror" que se publicó aquí. Mi error. Esto no va a funcionar en vainilla rubí.
Saroj
1

Cuando trato con un registro de base de datos , me gusta inicializar todos los valores vacíos con 0, usando el asistente de migración:

add_column :products, :price, :integer, default: 0
pastullo
fuente
0

Puede inicializar el descuento a 0 siempre que se garantice que su código no intente usarlo antes de que se inicialice. Supongo que eso eliminaría un cheque, no puedo pensar en otra cosa.

Ed S.
fuente
0
if discount.nil? || discount == 0
  [do something]
end
Abhinay Reddy Keesara
fuente
0

Prefiero usar un enfoque más limpio:

val.to_i.zero?

val.to_idevolverá a 0si val es a nil,

después de eso, todo lo que tenemos que hacer es verificar si el valor final es cero .

Ozesh
fuente
-1

La solución alternativa es usar Refinamientos, así:

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if discount.nothing?
  # do something
end
RichOrElse
fuente
-7

Creo que lo siguiente es lo suficientemente bueno para el código ruby. No creo que pueda escribir una prueba unitaria que muestre alguna diferencia entre esto y el original.

if discount != 0
end
Jeff Waltzer
fuente
8
Se evaluaría truesi el descuento fuera nil.
Andrew Grimm