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?


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 

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.


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? 傻傻 分不清楚


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


¿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.


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" "


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?


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.


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.


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.


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.


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.


¡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

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.