Como entender nulo vs. vazio vs. vazio no Ruby

1129

Encontro-me várias vezes à procura de uma definição clara das diferenças nil?, blank?e, empty?em Ruby on Rails. Aqui está o mais perto que eu cheguei:

  • blank?objetos são falsos, vazios ou uma sequência de espaços em branco. Por exemplo, "", " ", nil, [], e {}estão em branco.

  • nil? objetos são instâncias do NilClass.

  • empty?os objetos são específicos da classe e a definição varia de classe para classe. Uma cadeia está vazia se não tiver caracteres e uma matriz está vazia se não contiver itens.

Falta alguma coisa ou pode ser feita uma comparação mais rigorosa?

Arrel
fonte
26
Uma pegadinha é uma matriz vazia retorna falso para present?. Isso ocorre porque blank?retorna verdadeiro para uma matriz vazia.
Kris
4
Uma coisa boa é ver que :nil?é definido em ::Kernele substituído em ::NilClass, enquanto :empty?é implementado separadamente em muitas classes (nativamente em ::String, ::Array, ::Hash, e não de forma nativa em outras classes como ::Setde stdlib e ::ActiveRecord::Relationde trilhos). Portanto, :nil?está disponível em todas as subclasses ::Objecte também em todas as classes que incluem ::Kernelpor si só, onde :empty?devem ser implementadas ou incluídas especificamente em suas classes.
reescrito
Se você tentar entender todo o nilconceito, comece aqui .
217186 Totemmedli
[1] pry(main)> [].blank? => true
Michael

Respostas:

1437

.nil? pode ser usado em qualquer objeto e é verdadeiro se o objeto for nulo.

.empty? pode ser usado em strings, matrizes e hashes e retorna true se:

  • Comprimento da string == 0
  • Comprimento da matriz == 0
  • Comprimento do hash == 0

Correr .empty?em algo que é nulo lançará a NoMethodError.

É aí que .blank?entra. É implementado pelo Rails e operará em qualquer objeto, além de funcionar como .empty?strings, matrizes e hashes.

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

.blank? também avalia true em strings que não estão vazias, mas contêm apenas espaço em branco:

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

O Rails também fornece .present? , que retorna a negação de .blank?.

Pegue a matriz: blank?retornará falsemesmo se todos os elementos de uma matriz estiverem em branco. Para determinar o vazio neste caso, use all?com blank?, por exemplo:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 
Corban Brook
fonte
27
Conforme mencionado na pergunta, algumas cadeias não vazias contam como em branco.
1811 Andrew Grimm
1
Por que eles não substituem nada de vazio? se eles pudessem adicionar .blank?
Até 11/03
6
Também:false.blank? == true
Shannon
2
Eu mencionaria presence!
9788 Marc-André Lafortune
2
Como um complemento à pegada de matriz em branco que Tom está mencionando em sua resposta, saiba que isso pode levar a problemas de segurança nos quais um invasor pode usar código não preparado que simplesmente verifica a menos que params.nil? ou a menos que params.blank ?, e seja a causa de muitas discussões e trabalhos atualmente no Rails. Veja aqui para obter mais informações: github.com/rails/rails/issues/13420
Houen
675

Eu fiz esta tabela útil com todos os casos:

insira a descrição da imagem aqui

blank?, present?são fornecidos pelo Rails.

Julian Popov
fonte
57
Note-se que em branco? e presente? são apenas Rails. Eles retornam Exceção: NoMethodError no Ruby 2.0.0.
Lonny Eachus
17
Considere adicionar any?se alguma vez atualizar a tabela.
Dennis
blank?e present?não são " somente Rails ", eles são incluídos automaticamente pelo Rails, mas podem ser facilmente incluídos no código não-Rails usando as extensões principais do ActiveSupport. Veja stackoverflow.com/questions/4238867/…
the Tin Man
215

Apenas estenda a tabela de Julian:

insira a descrição da imagem aqui

Ref: vazio? Em branco? Nulo? 傻傻 分不清楚

Sibevin Wang
fonte
1
@Sibevin Wang, baixei esta tabela e a usei em algumas das minhas respostas adicionando os créditos a você. Espero que você não se importe :) Parabéns a este grande esforço!
Lahiru 21/07
1
Enumerable#any?é baunilha Ruby, ele não deve ser listado em "trilhos apenas"
daniero
1
@daniero Obrigado pelo seu lembrete, a tabela está atualizada.
Sibevin Wang 4/09/16
Tipos numéricos também têm .zero?e.nonzero?
DaveMongoose
63

Dica rápida: !obj.blank? == obj.present?

Pode ser útil / mais fácil para os olhos em algumas expressões

Alexander Malfait
fonte
existe algo equivalente a! obj.nil?
Kirk
present?é parte de active_support, confira aqui sobre o que incluir para obtê-lo: stackoverflow.com/a/4648704/1569
Fator Místico
2
@Kirk: !! obj é equivalente a! Obj.nil?
Mohamed Hafez
4
@MohamedHafez Não, não é. !!false
precisa saber é o seguinte
Agh, @ Ajedi32 boa captura! equivalente a essa exceção.
Mohamed Hafez
52

Uma diferença é que .nil?e .empty?são os métodos fornecidos pela linguagem de programação Ruby, ao passo que .blank?é algo adicionado pelo framework de desenvolvimento web Rails.

Andrew Grimm
fonte
49

insira a descrição da imagem aqui

  • Tudo o que é nil?éblank?
  • Tudo o que é empty?éblank?
  • Nada do que é empty?énil?
  • Nada do que é nil?éempty?

tl; dr - use somente blank?& a present?menos que você queira distinguir entre ""e" "

Steve
fonte
2
uau! você recebeu meu +1
Am33d 01/08/19
16

Um caso especial é ao tentar avaliar se um valor booleano é nulo:

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

Nesse caso, a recomendação seria usar .nil?

Alan H
fonte
14

Apenas uma pequena nota sobre a any?recomendação: ele está certo de que geralmente é equivalente !empty?. No entanto, any?retornará truea uma sequência de apenas espaço em branco (ala " ").

E, claro, veja também o comentário 1.9 acima.

Davemyron
fonte
No Rails, qualquer string contendo apenas caracteres de espaço em branco é "em branco": "\ n \ r \ t" .blank? # => true
Lonny Eachus
13

Não esqueça o any?que é geralmente !empty?. No Rails, normalmente verifico a presença de algo no final de uma declaração com if somethingou unless somethingentão uso blank?quando necessário, pois parece funcionar em qualquer lugar.


fonte
4
.qualquer? não funciona com strings no ruby ​​1.9, como .any? requer enumerável, e a string #, por si só, não funciona no ruby ​​1.9.
1813 Andrew Grimm
4
Cuidado any?para verificar o não vazio. Retorna false se você tiver uma matriz de valores falsos. Uma maneira de contornar isso é passar um bloco sempre verdadeiro:, [nil, false].any?{ true }mas !empty?é mais curto e você não se lembra do comportamento estranho.
Kelvin
12

nil?é um método Ruby padrão que pode ser chamado em todos os objetos e retorna truese o objeto for nil:

b = nil
b.nil? # => true

empty?é um método Ruby padrão que pode ser chamado em alguns objetos, como Strings, Arrays e Hashes, e retorna truese esses objetos não contiverem elemento:

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

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

empty?não pode ser chamado em nilobjetos.

blank?é um método Rails que pode ser chamado em nilobjetos e em objetos vazios.

neha
fonte
7

Todo mundo já explicou bem qual é a diferença.

Eu gostaria de adicionar no Ruby On Rails, é melhor usar obj.blank?ou em obj.present?vez de obj.nil?ouobj.empty? .

obj.blank?controla todos os tipos nil, '', [], {}, e retornos truese os valores não estão disponíveis e retornos falsese os valores estão disponíveis em qualquer tipo de objeto.

Manish Shrivastava
fonte
5

exists?O método pode ser usado para verificar se os dados existem no banco de dados ou não. Retorna valores booleanos trueou false.

Kelvin
fonte
Funciona apenas na classe de modelo!
Roger
4

Trilhos 4

uma alternativa para @ corban-brook 's Array gotcha: blank? para verificar se uma matriz contém apenas valores vazios e pode ser considerada em branco? verdade:

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

também se poderia fazer:

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

nil?pode ser usado em qualquer objeto. Determina se o objeto tem algum valor ou não, incluindo valores 'em branco'.

Por exemplo:

example = nil
example.nil?  # true

"".nil?  # false

Basicamente nil? , somente retornará true se o objeto for de fato igual a 'nil'.

empty?é chamado apenas em objetos que são considerados uma coleção. Isso inclui coisas como strings (uma coleção de caracteres), hashes (uma coleção de pares de chave / valor) e matrizes (uma coleção de objetos arbitrários). empty?retorna true é que não há itens na coleção.

Por exemplo:

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

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

Observe que empty?não é possível chamar objetos nulos, pois objetos nulos não são uma coleção e isso gera uma exceção.

Observe também que, mesmo que os itens de uma coleção estejam em branco, isso não significa que uma coleção esteja vazia.

blank?é basicamente uma combinação de nil?e empty?É útil para verificar objetos que você supõe serem coleções, mas também pode ser nulo.

Chitra
fonte