Cómo entender nulo vs. vacío vs. blanco en Ruby

1129

Me encuentro en repetidas ocasiones en busca de una definición clara de las diferencias de nil?, blank?y empty?en Ruby on Rails. Aquí está lo más cerca que he estado:

  • blank?los objetos son falsos, vacíos o una cadena de espacio en blanco. Por ejemplo, "", " ", nil, [], y {}están en blanco.

  • nil? Los objetos son instancias de NilClass.

  • empty?los objetos son específicos de la clase, y la definición varía de una clase a otra. Una cadena está vacía si no tiene caracteres, y una matriz está vacía si no contiene elementos.

¿Falta algo o se puede hacer una comparación más estricta?

Arrel
fuente
26
Un problema es que una matriz vacía devuelve falso para present?. Lo cual se debe a que blank?devuelve verdadero para una matriz vacía.
Kris
44
Una cosa buena es ver que :nil?se define en ::Kernely cambiados en ::NilClass, mientras :empty?se implementa por separado en muchas clases (de forma nativa en ::String, ::Array, ::Hash, y no de forma nativa en otras clases como ::Setde stdlib y ::ActiveRecord::Relationde rieles). Por :nil?lo tanto, está disponible en todas las subclases ::Objecty también en cada clase que incluye ::Kernelpor sí misma, donde :empty?debe implementarse o incluirse específicamente en sus clases.
reescrito el
Si intenta comprender todo el nilconcepto, comience aquí .
totymedli
[1] pry(main)> [].blank? => true
Michael

Respuestas:

1437

.nil? se puede usar en cualquier objeto y es verdadero si el objeto es nulo.

.empty? se puede usar en cadenas, matrices y hashes y devuelve verdadero si:

  • Longitud de cadena == 0
  • Longitud de matriz == 0
  • Longitud del hash == 0

Correr .empty?en algo que es nulo arrojará un NoMethodError.

Ahí es donde .blank?entra. Está implementado por Rails y funcionará en cualquier objeto, así como .empty?en cadenas, matrices y hashes.

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

.blank? también evalúa true en cadenas que no están vacías pero que solo contienen espacios en blanco:

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

Rails también proporciona .present? , lo que devuelve la negación de .blank?.

Array gotcha: blank?regresará falseincluso si todos los elementos de una matriz están en blanco. Para determinar el espacio en blanco en este caso, use all?con blank?, por ejemplo:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 
Corban Brook
fuente
27
Como se menciona en la pregunta, algunas cadenas no vacías cuentan como en blanco.
Andrew Grimm
1
¿Por qué no han sobrescrito el vacío de cero? si pudieran agregar .blank?
tillda
66
También:false.blank? == true
Shannon
2
Yo mencionaría presence!
Marc-André Lafortune
2
Como una adición al truco de matriz en blanco que Tom está mencionando en su respuesta, tenga en cuenta que esto puede conducir a problemas de seguridad en los que un atacante puede usar código no preparado que simplemente verifica a menos que params.nil? o a menos que params.blank ?, y es la causa de mucha discusión y trabajo actualmente en Rails. Consulte aquí para obtener más información: github.com/rails/rails/issues/13420
Houen
675

Hice esta útil tabla con todos los casos:

ingrese la descripción de la imagen aquí

blank?, present?son proporcionados por Rails.

Julian Popov
fuente
57
Cabe señalar que en blanco? y presente? son solo rieles. Devuelven Exception: NoMethodError en Ruby 2.0.0.
Lonny Eachus
17
Considere agregar any?si alguna vez actualiza la tabla.
Dennis
blank?y present?no son " solo Rails ", Rails los incluye automáticamente, pero se pueden incluir fácilmente en código que no sea Rails mediante las extensiones Core de ActiveSupport. Ver stackoverflow.com/questions/4238867/…
The Tin Man
215

Solo extienda la mesa de Julian:

ingrese la descripción de la imagen aquí

Ref: vacío? En blanco? Nulo? 傻傻 分不清楚

Sibevin Wang
fuente
1
@Sibevin Wang, descargué esta tabla y la utilicé en algunas de mis respuestas para agregarle los créditos. Espero que no te importe :) Felicitaciones a este gran esfuerzo!
Lahiru
1
Enumerable#any?es vainilla Ruby, no debería figurar en "solo rieles"
daniero
1
@daniero Gracias por tu recordatorio, la tabla se actualiza.
Sibevin Wang
Los tipos numéricos también tienen .zero?y.nonzero?
DaveMongoose
63

Consejo rapido: !obj.blank? == obj.present?

Puede ser útil / más fácil para la vista en algunas expresiones

Alexander Malfait
fuente
¿hay algo equivalente a! obj.nil?
Kirk
present?es parte de active_support, verifique aquí qué incluir para obtenerlo: stackoverflow.com/a/4648704/1569
Factor Mystic
2
@Kirk: !! obj es equivalente a! Obj.nil?
Mohamed Hafez
44
@MohamedHafez No, no lo es. !!false
Ajedi32
Agh, @ Ajedi32 buena captura! equivalente con esa única excepción.
Mohamed Hafez
52

Una diferencia es que .nil?y .empty?son métodos que proporciona el lenguaje de programación Ruby, mientras que .blank?es algo agregado por el marco de desarrollo web Rails.

Andrew Grimm
fuente
49

ingrese la descripción de la imagen aquí

  • Todo lo que es nil?esblank?
  • Todo lo que es empty?esblank?
  • Nada de lo que empty?esnil?
  • Nada de lo que nil?esempty?

tl; dr: solo use blank?& a present?menos que desee distinguir entre ""y" "

Steve
fuente
2
woah! tienes mi +1
Am33d
16

Un caso especial es cuando se trata de evaluar si un valor booleano es nulo:

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

En este caso, la recomendación sería utilizar .nil?

Alan H
fuente
14

Solo una pequeña nota sobre la any?recomendación: tiene razón en que generalmente es equivalente a !empty?. Sin embargo, any?volverá truea una cadena de solo espacios en blanco (ala " ").

Y, por supuesto, vea el comentario 1.9 anterior también.

davemyron
fuente
En Rails, cualquier cadena que contenga solo caracteres de espacio en blanco está "en blanco": "\ n \ r \ t". ¿En blanco? # => verdadero
Lonny Eachus
13

No olvides any?cuál es generalmente !empty?. En Rails, generalmente verifico la presencia de algo al final de una declaración if somethingo unless somethingluego lo uso blank?cuando sea necesario, ya que parece funcionar en todas partes.


fuente
44
.¿ninguna? no funciona con cadenas en ruby ​​1.9, como .any? requiere enumerable, y la cadena # cada una por sí sola no funciona en ruby ​​1.9.
Andrew Grimm
44
Cuidado con el any?control de no vacío. Devuelve falso si tiene una matriz de valores falsos. Una forma de evitarlo es pasar un bloqueo siempre verdadero: [nil, false].any?{ true }pero !empty?es más corto y no recuerdas el comportamiento extraño.
Kelvin
12

nil?es un método estándar de Ruby que se puede invocar en todos los objetos y devuelve truesi el objeto es nil:

b = nil
b.nil? # => true

empty?es un método estándar de Ruby que se puede invocar en algunos objetos como Strings, Arrays y Hashes y devuelve truesi estos objetos no contienen ningún elemento:

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

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

empty?no se puede invocar en nilobjetos.

blank?es un método Rails que se puede invocar tanto en nilobjetos como en objetos vacíos.

neha
fuente
7

Todos los demás han explicado bien cuál es la diferencia.

Me gustaría agregar Ruby On Rails, es mejor usar obj.blank?o en obj.present?lugar de obj.nil?o obj.empty?.

obj.blank?Sirve para todo tipo nil, '', [], {}, y rendimientos truesi los valores no están disponibles y rendimientos falsesi los valores están disponibles en cualquier tipo de objeto.

Shrivastava Manish
fuente
5

exists?El método se puede utilizar para verificar si los datos existen en la base de datos o no. Devuelve valores booleanos trueo false.

Kelvin
fuente
¡Funciona solo en clase modelo!
Roger,
4

Carriles 4

una alternativa a 'corray-brook' s 'Array gotcha: blank?' para verificar si una matriz solo contiene valores vacíos y puede considerarse en blanco? cierto:

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

uno también podría hacer:

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

nil?Se puede utilizar en cualquier objeto. Determina si el objeto tiene algún valor o no, incluidos los valores 'en blanco'.

Por ejemplo:

example = nil
example.nil?  # true

"".nil?  # false

Básicamente nil?solo devolverá verdadero si el objeto es de hecho igual a 'nulo'.

empty?solo se invoca en objetos que se consideran una colección. Esto incluye cosas como cadenas (una colección de caracteres), hashes (una colección de pares clave / valor) y matrices (una colección de objetos arbitrarios).empty?devuelve verdadero si no hay elementos en la colección.

Por ejemplo:

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

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

Darse cuenta de empty? no se puede invocar en objetos nulos ya que los objetos nulos no son una colección y generará una excepción.

También tenga en cuenta que incluso si los elementos de una colección están en blanco, no significa que una colección esté vacía.

blank?es básicamente una combinación de nil?y empty?es útil para verificar objetos que supones que son colecciones, pero también podrían ser nulos.

Chitra
fuente