Comment comprendre zéro vs vide vs vide dans Ruby

1129

Je me retrouve à plusieurs reprises à la recherche d'une définition claire des différences de nil?, blank?et empty?en Ruby on Rails. Voici le plus proche que je suis venu:

  • blank?les objets sont faux, vides ou une chaîne d'espaces. Par exemple, "", " ", nil, []et {}sont vides.

  • nil? les objets sont des instances de NilClass.

  • empty?les objets sont spécifiques à la classe et la définition varie d'une classe à l'autre. Une chaîne est vide si elle n'a pas de caractères et un tableau est vide s'il ne contient aucun élément.

Y a-t-il quelque chose qui manque ou une comparaison plus étroite qui peut être faite?

Arrel
la source
26
Un gotcha est un tableau vide qui renvoie false pour present?. En effet, blank?renvoie true pour un tableau vide.
Kris
4
Une bonne chose est de voir que :nil?est défini sur ::Kernelet réécrite sur ::NilClass, tout :empty?est mis en œuvre séparément sur de nombreuses classes ( en mode natif sur ::String, ::Array, ::Hashet non en mode natif sur d' autres classes comme ::Setde stdlib et ::ActiveRecord::Relationde rails). Donc, :nil?est disponible dans toutes les sous-classes de ::Objectet aussi dans chaque classe qui comprend ::Kernelpar elle-même, où :empty?doit être implémentée ou incluse spécifiquement dans vos classes.
réécrit
Si vous essayez de comprendre tout le nilconcept, commencez ici .
totymedli
[1] pry(main)> [].blank? => true
Michael

Réponses:

1437

.nil? peut être utilisé sur n'importe quel objet et est vrai si l'objet est nul.

.empty? peut être utilisé sur des chaînes, des tableaux et des hachages et renvoie true si:

  • Longueur de chaîne == 0
  • Longueur du tableau == 0
  • Longueur du hachage == 0

Courir .empty?sur quelque chose de nul jettera a NoMethodError.

C'est là .blank?qu'intervient. Il est implémenté par Rails et fonctionnera sur n'importe quel objet ainsi que .empty?sur des chaînes, des tableaux et des hachages.

nil.blank? == true
false.blank? == true
[].blank? == true
{}.blank? == true
"".blank? == true
5.blank? == false
0.blank? == false

.blank? évalue également true sur les chaînes qui ne sont pas vides mais ne contiennent que des espaces:

"  ".blank? == true
"  ".empty? == false

Rails fournit également .present? , qui renvoie la négation de .blank?.

Array gotcha: blank?retournera falsemême si tous les éléments d'un tableau sont vides. Pour déterminer le vide dans ce cas, utilisez all?avec blank?, par exemple:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 
Ruisseau Corban
la source
27
Comme mentionné dans la question, certaines chaînes non vides comptent comme vides.
Andrew Grimm
1
Pourquoi n'ont-ils pas écrasé le vide de zéro? s'ils pouvaient ajouter .blank?
tillda
6
Aussi:false.blank? == true
Shannon
2
Je mentionnerais presence!
Marc-André Lafortune
2
En plus du piège de tableau entièrement vierge que Tom mentionne dans sa réponse, sachez que cela peut entraîner des problèmes de sécurité où un attaquant peut utiliser du code non préparé qui vérifie simplement sauf si params.nil? ou à moins que params.blank?, et est la cause de beaucoup de discussions et de travail actuellement dans Rails. Voir ici pour plus d'informations: github.com/rails/rails/issues/13420
Houen
675

J'ai fait ce tableau utile avec tous les cas:

entrez la description de l'image ici

blank?, present?sont fournis par Rails.

Julian Popov
la source
57
Il convient de noter que vide? et présent? sont Rails uniquement. Ils renvoient Exception: NoMethodError dans Ruby 2.0.0.
Lonny Eachus
17
Pensez à ajouter any?si vous mettez à jour le tableau.
Dennis
blank?et present?ne sont pas " Rails uniquement ", ils sont automatiquement inclus par Rails mais peuvent facilement être inclus dans du code non-Rails en utilisant les extensions Core d'ActiveSupport. Voir stackoverflow.com/questions/4238867/…
The Tin Man
215

Il suffit d'étendre la table de Julian:

entrez la description de l'image ici

Réf: vide? Vide? Nul? 傻傻 分不清楚

Sibevin Wang
la source
1
@Sibevin Wang, j'ai téléchargé ce tableau et je l'ai utilisé dans certaines de mes réponses en vous ajoutant les crédits. J'espère que cela ne vous dérange pas :) Félicitations à ce grand effort!
Lahiru
1
Enumerable#any?est vanilla Ruby, il ne devrait pas être répertorié sous "rails uniquement"
daniero
1
@daniero Merci pour votre rappel, le tableau est mis à jour.
Sibevin Wang
Les types numériques ont également .zero?et.nonzero?
DaveMongoose
63

Conseil rapide: !obj.blank? == obj.present?

Peut être pratique / plus agréable pour les yeux dans certaines expressions

Alexander Malfait
la source
y a-t-il quelque chose d'équivalent à! obj.nil?
Kirk
present?fait partie de active_support, vérifiez ici ce qu'il faut inclure pour l'obtenir: stackoverflow.com/a/4648704/1569
Factor Mystic
2
@Kirk: !! obj est équivalent à! Obj.nil?
Mohamed Hafez
4
@MohamedHafez Non ce n'est pas le cas. !!false
Ajedi32
Agh, @ Ajedi32 bonne prise! équivalent à cette seule exception.
Mohamed Hafez
52

Une différence est que .nil?et .empty?sont des méthodes qui sont fournis par le langage de programmation Ruby, alors .blank?quelque chose ajoutée par le cadre de développement web Rails.

Andrew Grimm
la source
49

entrez la description de l'image ici

  • Tout ce qui nil?estblank?
  • Tout ce qui empty?estblank?
  • Rien de ce qui empty?estnil?
  • Rien de ce qui nil?estempty?

tl; dr - utilisez uniquement blank?& present?sauf si vous voulez faire la distinction entre ""et" "

Steve
la source
2
woah! vous avez obtenu mon +1
Am33d
16

Un cas particulier consiste à évaluer si une valeur booléenne est nulle:

false.present? == false
false.blank? == true
false.nil? == false

Dans ce cas, la recommandation serait d'utiliser .nil?

Alan H
la source
14

Juste une petite note au sujet de la any?recommandation: Il a raison de dire qu'elle est généralement équivalente à !empty?. Cependant, any?reviendra trueà une chaîne de simples espaces (ala " ").

Et bien sûr, voir aussi le commentaire 1.9 ci-dessus.

davemyron
la source
Dans Rails, toute chaîne contenant uniquement des caractères blancs est "vide": "\ n \ r \ t" .blank? # => true
Lonny Eachus
13

N'oubliez pas any?ce qui est généralement !empty?. Dans Rails, je vérifie généralement la présence de quelque chose à la fin d'une déclaration avec if somethingou unless somethingensuite j'utilise blank?où cela est nécessaire car il semble fonctionner partout.


la source
4
.tout? ne fonctionne pas avec les chaînes dans ruby ​​1.9, comme .any? requiert un énumérable, et la chaîne # seule ne fonctionne pas dans ruby ​​1.9.
Andrew Grimm
4
Attention any?à vérifier le non-vide. Il renvoie false si vous avez un tableau de valeurs de falsification. Un moyen de contourner cela est de passer un bloc toujours vrai:, [nil, false].any?{ true }mais !empty?est plus court et vous ne vous souvenez pas du comportement étrange.
Kelvin
12

nil?est une méthode Ruby standard qui peut être appelée sur tous les objets et renvoie truesi l'objet est nil:

b = nil
b.nil? # => true

empty?est une méthode Ruby standard qui peut être appelée sur certains objets tels que Strings, Arrays et Hashes et renvoie truesi ces objets ne contiennent aucun élément:

a = []
a.empty? # => true

b = ["2","4"]
b.empty? # => false

empty?ne peut pas être appelé sur des nilobjets.

blank?est une méthode Rails qui peut être appelée nilaussi bien sur des objets que sur des objets vides.

neha
la source
7

Tout le monde a bien expliqué quelle est la différence.

Je voudrais ajouter Ruby On Rails, il vaut mieux utiliser obj.blank?ou à la obj.present?place de obj.nil?ou obj.empty?.

obj.blank? gère tous les types nil , '', [], {}et retourne truesi les valeurs ne sont pas disponibles et les rendements falsesi les valeurs sont disponibles sur tout type d'objet.

Manish Shrivastava
la source
5

exists?peut être utilisée pour vérifier si les données existent ou non dans la base de données. Il renvoie des valeurs booléennes soit trueou false.

Kelvin
la source
Fonctionne uniquement sur la classe modèle!
Roger
4

Rails 4

une alternative à 'Array gotcha: blank?' de @ corban-brook pour vérifier si un tableau ne contient que des valeurs vides et peut être considéré comme vide? vrai:

[ nil, '' ].all? &:blank? == true

on pourrait aussi faire:

[nil, '', "", " ",' '].reject(&:blank?).blank? == true
mahatmanich
la source
3

nil?peut être utilisé sur n'importe quel objet. Il détermine si l'objet a une valeur ou non, y compris des valeurs «vides».

Par exemple:

example = nil
example.nil?  # true

"".nil?  # false

Fondamentalement nil?, ne retournera vrai que si l'objet est en fait égal à «néant».

empty?est uniquement appelé sur les objets considérés comme une collection. Cela inclut des choses comme des chaînes (une collection de caractères), des hachages (une collection de paires clé / valeur) et des tableaux (une collection d'objets arbitraires).empty?renvoie true s'il n'y a aucun élément dans la collection.

Par exemple:

"".empty? # true
"hi".empty?   # false
{}.empty?  # true
{"" => ""}.empty?   # false
[].empty?   # true
[nil].empty?  # false

nil.empty?  # NoMethodError: undefined method `empty?' for nil:NilClass

Notez qu'il empty?ne peut pas être appelé sur des objets nil car les objets nil ne sont pas une collection et cela déclenchera une exception.

Notez également que même si les éléments d'une collection sont vides, cela ne signifie pas qu'une collection est vide.

blank?est essentiellement une combinaison de nil?et empty?il est utile pour vérifier les objets que vous supposez être des collections, mais qui peuvent également être nuls.

Chitra
la source