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?

hectorsq
la source
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
Dejan Simic
la source
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.

madlep
la source
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.

réécrit
la source
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
Dejan Simic
la source
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?
ndnenkov
la source
"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
17
if (discount||0) != 0
  #...
end
Raimonds Simanovskis
la source
Ceci est ma réponse préférée
Wilson Freitas
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.

Jeremy Ruten
la source
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
oivoodoo
la source
attention: 0.1.to_i == 0
Simon B.
3
if discount and discount != 0
  ..
end

mise à jour, il sera falsepourdiscount = false

rubyprince
la source
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.

Dave GW
la source
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.

Saroj
la source
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
pastullo
la source
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.

Ed S.
la source
0
if discount.nil? || discount == 0
  [do something]
end
Abhinay Reddy Keesara
la source
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 .

Ozesh
la source
-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
RichOrElse
la source
-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
Jeff Waltzer
la source
8
Il évaluerait truesi la remise était nil.
Andrew Grimm