Vérifier si une variable n'est pas nulle et non nulle en rubis


271

J'utilise le code suivant pour vérifier si une variable n'est pas nulle et non nulle

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

Y a-t-il une meilleure manière de faire cela?


1
Probablement parce que c'est une copie exacte de stackoverflow.com/questions/209495/… .
David Nehme

1
Que doit-il faire si discountc'est faux?
Andrew Grimm

1
Je pense que discount.in? [0, nil]la façon la plus propre possible
intmarinoreturn0

Réponses:


428
sauf discount.nil? || remise == 0
  # ...
fin

31
Utilisez 'ou' au lieu de ||
Orion Edwards

93
@ orion-edwards pourquoi?
NARKOZ

39
L'utilisation de «ou» est dangereuse. 'ou' a une présence inférieure à l'opérateur = ', donc le comportement suivant est inattendu: a = false ou true #a est faux après cette déclaration
Tom G

20
@xiy actuellement le guide recommande de faire semblant ou et et n'existent pas (|| est-ce ou && et?)
user3125280

67
Présente "Ruby Style Guide" The and and or keywords are banned. It's just not worth it. Always use && and || instead.. Et c'est vrai, pour des raisons de David et 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

Méfiez-vous des avertissements habituels ... grande puissance / responsabilité, correction de singe menant au côté obscur, etc.


28

ok, après 5 ans se sont écoulés ....

if discount.try :nonzero?
  ...
end

Il est important de noter qu'il tryest défini dans la gemme ActiveSupport, il n'est donc pas disponible en rubis uni.


7
Notez qu'il s'agit d'une réponse spécifique aux rails . Le rubis vanille n'a pas de tryméthode.
Tom Lord

Correct. Bien qu'il ressemble davantage à ActiveSupport, qui est une dépendance beaucoup plus légère et largement utilisée que les rails complets. Quoi qu'il en soit, la réponse de @ ndn est la bonne.
réécrit le

Modifié pour utiliser la navigation en toute sécurité
réécrit le

1
La réponse duplique maintenant stackoverflow.com/a/34819818/1954610 ... Je pense qu'il est utile de la laisser trypour montrer l'option alternative (c'est pourquoi elle a été votée en premier lieu!), Tant qu'il est clair le lecteur qui ActiveSupportn'est pas du rubis vanille.
Tom Lord

Point pris, réponse annulée.
réécrit le

27
sauf si [nul, 0] .inclut? (remise) 
  # ...
fin

13
Belle? Oui. Lisible? Pas vraiment.
El Ninja Trepador

1
Je trouve cela parfaitement lisible, et je le préférerais à une nouvelle classe. Bien joué.
colincr

L'approche la plus rubyiste de gérer deux conditions.
Yugendran

23

À partir de Ruby 2.3.0, vous pouvez combiner l'opérateur de navigation sécurisée ( &.) avec Numeric#nonzero?. &.renvoie nilsi l'instance était nilet nonzero?- si le nombre était 0:

if discount&.nonzero?
  # ...
end

Ou suffixe:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Ce n'est pas sûr à utiliser sur des objets arbitraires.
Tom Lord

2
@TomLord, comme indiqué dans le commentaire précédent, cela n'était pas destiné à fonctionner avec des objets arbitraires. Au lieu de cela, il s'agit du cas où vous avez quelque chose que vous savez être un nombre, mais qui pourrait aussi l'être nil.
ndnenkov

Je voudrais que ce fait soit clair dans la réponse, plutôt que quelqu'un le lisant et ne repérant pas l'avertissement dans les commentaires.
Tom Lord

@TomLord, c'est indiqué dans la réponse " nonzero?- si le nombre était 0" . De même, la nécessité de vérifier si un objet complètement arbitraire se 0pose est extrêmement rarement comparée à celle de vérifier un nombre qui peut ou non l'être nil. Elle est donc presque implicite. Même si quelqu'un fait en quelque sorte l'hypothèse contraire, il comprendra instantanément ce qui se passe lorsqu'il essaie de l'exécuter.
ndnenkov


15

Vous pouvez faire ceci:

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

L'ordre est important ici, car s'il l' discountest nil, alors il n'aura pas de zero?méthode. L'évaluation des courts-circuits de Ruby devrait cependant l'empêcher d'essayer d'évaluer discount.zero?si discountc'est le cas nil.


11

Vous pouvez convertir votre ligne vide en valeur entière et vérifier zéro?.

"".to_i.zero? => true
nil.to_i.zero? => true

attention: 0.1.to_i == 0
Simon B.

3
if discount and discount != 0
  ..
end

mise à jour, il sera falsepourdiscount = false


2

Vous pouvez profiter de la méthode NilClassfournie #to_i, qui renverra zéro pour les nilvaleurs:

unless discount.to_i.zero?
  # Code here
end

S'il discountpeut s'agir de nombres fractionnaires, vous pouvez utiliser à la #to_fplace, pour éviter que le nombre ne soit arrondi à zéro.


N'est-ce pas la même chose que la réponse de @ oivoodo?
Cary Swoveland,

Ne fonctionne pas pour les objets arbitraires . "".to_i == "foo".to_i == "0".to_i == 0. Votre méthode créera toutes sortes de contraintes de type non intentionnelles. Il échouera également avec un NoMethodErrorsi discountne répond pas to_i.
Tom Lord

2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Si nous passons "" il retournera faux alors vide? renvoie vrai. Il en va de même lorsque data = false blank? renvoie true pour nil, false, vide ou une chaîne d'espaces. Il est donc préférable d'utiliser des blancs? pour éviter également les chaînes vides.


1
blank?est une méthode spécifique aux rails et non disponible en rubis vanille.
Tom Lord

Vous avez raison!! Je pensais que cela est lié à la balise "ror", donc publié ici. Mon erreur. Ça ne marchera pas en rubis vanille.
Saroj

1

Lorsque je traite un enregistrement de base de données , j'aime initialiser toutes les valeurs vides avec 0, en utilisant l'aide à la migration:

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

0

Vous pouvez initialiser la remise à 0 tant que votre code est garanti de ne pas essayer de l'utiliser avant son initialisation. Cela supprimerait un chèque, je suppose, je ne peux penser à rien d'autre.



0

Je préfère utiliser une approche plus propre:

val.to_i.zero?

val.to_irenverra un 0si val est un nil,

après cela, tout ce que nous devons faire est de vérifier si la valeur finale est un zéro .


-1

La solution alternative consiste à utiliser les raffinements, comme ceci:

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

-7

Je crois que ce qui suit est assez bon pour le code ruby. Je ne pense pas que je pourrais écrire un test unitaire qui montre une différence entre cela et l'original.

if discount != 0
end

8
Il évaluerait truesi la remise était nil.
Andrew Grimm
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.