Wie man in Ruby null gegen leer gegen leer versteht

1129

Ich finde ich immer wieder für eine klare Definition der Unterschiede zu suchen nil?, blank?und empty?in Ruby on Rails. Hier ist der nächste, den ich gekommen bin:

  • blank?Objekte sind falsch, leer oder eine Leerzeichenfolge. Zum Beispiel "", " ", nil, [], und {}sind leer.

  • nil? Objekte sind Instanzen von NilClass.

  • empty?Objekte sind klassenspezifisch und die Definition variiert von Klasse zu Klasse. Eine Zeichenfolge ist leer, wenn sie keine Zeichen enthält, und ein Array ist leer, wenn sie keine Elemente enthält.

Fehlt etwas oder kann ein genauerer Vergleich durchgeführt werden?

Arrel
quelle
26
Ein Gotcha ist ein leeres Array, für das false zurückgegeben wird present?. Dies liegt daran blank?, dass für ein leeres Array true zurückgegeben wird.
Kris
4
Eine nette Sache ist zu sehen , dass :nil?ist definiert auf ::Kernelund außer Kraft gesetzt auf ::NilClass, während :empty?umgesetzt wird separat auf vielen Klassen (nativ auf ::String, ::Array, ::Hashund nicht nativ auf anderen Klassen wie ::Setaus stdlib und ::ActiveRecord::Relationvon Schienen). Ist :nil?also in allen Unterklassen von ::Objectund auch in jeder Klasse verfügbar , die ::Kernelfür sich selbst enthält, wo :empty?sie implementiert oder speziell in Ihre Klassen aufgenommen werden muss.
Umgeschrieben am
Wenn Sie versuchen, das gesamte nilKonzept zu verstehen, beginnen Sie hier .
Totymedli
[1] pry(main)> [].blank? => true
Michael

Antworten:

1437

.nil? kann für jedes Objekt verwendet werden und ist wahr, wenn das Objekt Null ist.

.empty? kann für Strings, Arrays und Hashes verwendet werden und gibt true zurück, wenn:

  • Stringlänge == 0
  • Array-Länge == 0
  • Hash-Länge == 0

Wenn Sie .empty?auf etwas laufen , das gleich Null ist, wird a geworfen NoMethodError.

Hier .blank?kommt es ins Spiel . Es wird von Rails implementiert und funktioniert mit jedem Objekt sowie mit .empty?Strings, Arrays und Hashes.

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

.blank? wertet true auch für Zeichenfolgen aus, die nicht leer sind, aber nur Leerzeichen enthalten:

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

Rails bietet auch .present? , was die Negation von zurückgibt .blank?.

Array gotcha: Gibt blank?zurück, falseauch wenn alle Elemente eines Arrays leer sind. Um zu bestimmen , Geistlosigkeit in diesem Fall der Verwendung all?mit blank?, zum Beispiel:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 
Corban Brook
quelle
27
Wie in der Frage erwähnt, gelten einige nicht leere Zeichenfolgen als leer.
Andrew Grimm
1
Warum haben sie nil's .empty nicht überschrieben? ob sie .blank hinzufügen könnten?
Bis zum
6
Auch:false.blank? == true
Shannon
2
Ich würde erwähnen presence!
Marc-André Lafortune
2
Beachten Sie, dass dies zu Sicherheitsproblemen führen kann, bei denen ein Angreifer unvorbereiteten Code verwenden kann, der nur nach params.nil sucht. oder es sei denn, params.blank?, und ist der Grund für viele Diskussionen und Arbeiten, die derzeit in Rails ausgeführt werden. Weitere Informationen finden Sie hier: github.com/rails/rails/issues/13420
Houen
675

Ich habe diese nützliche Tabelle mit allen Fällen erstellt:

Geben Sie hier die Bildbeschreibung ein

blank?, present?Sind durch Schienen vorgesehen.

Julian Popov
quelle
57
Es sollte beachtet werden, dass leer? und anwesend? sind nur Schienen. Sie geben die Ausnahme: NoMethodError in Ruby 2.0.0 zurück.
Lonny Eachus
17
Erwägen Sie das Hinzufügen, any?wenn Sie die Tabelle jemals aktualisieren.
Dennis
blank?und present?sind nicht "nur Rails ", sondern werden automatisch von Rails aufgenommen, können jedoch mithilfe der Core-Erweiterungen von ActiveSupport problemlos in Nicht-Rails-Code aufgenommen werden. Siehe stackoverflow.com/questions/4238867/…
Tin Man
215

Erweitern Sie einfach Julians Tisch:

Geben Sie hier die Bildbeschreibung ein

Ref: leer? Leer? Null? 傻傻 分不清楚

Sibevin Wang
quelle
1
@Sibevin Wang, ich habe diese Tabelle heruntergeladen und in einigen meiner Antworten verwendet, um Ihnen die Credits hinzuzufügen. Hoffe es macht dir nichts aus :) Ein großes Lob an diese große Anstrengung!
Lahiru
1
Enumerable#any?ist Vanille Ruby, es sollte nicht unter "Nur Schienen" aufgeführt werden
Daniero
1
@daniero Vielen Dank für Ihre Erinnerung, die Tabelle wird aktualisiert.
Sibevin Wang
Numerische Typen haben auch .zero?und.nonzero?
DaveMongoose
63

Kurzer Tipp: !obj.blank? == obj.present?

Kann in einigen Ausdrücken praktisch / augenschonender sein

Alexander Malfait
quelle
Gibt es etwas Äquivalentes zu! obj.nil?
Kirk
present?ist Teil von active_support. Überprüfen Sie hier, was enthalten sein soll, um es zu erhalten: stackoverflow.com/a/4648704/1569
Factor Mystic
2
@ Kirk: !! obj ist gleichbedeutend mit! Obj.nil?
Mohamed Hafez
4
@MohamedHafez Nein, ist es nicht. !!false
Ajedi32
Agh, @ Ajedi32 guter Fang! äquivalent mit dieser einen Ausnahme.
Mohamed Hafez
52

Ein Unterschied besteht darin , dass .nil?und .empty?Methoden sind, die von der Programmiersprache zur Verfügung gestellt werden , Rubin, während .blank?etwas hinzugefügt durch den Web - Entwicklungs - Framework Rails.

Andrew Grimm
quelle
49

Geben Sie hier die Bildbeschreibung ein

  • Alles was ist nil?istblank?
  • Alles was ist empty?istblank?
  • Nichts was empty?istnil?
  • Nichts was nil?istempty?

tl; dr - verwenden Sie nur blank?&, es present?sei denn, Sie möchten zwischen ""und unterscheiden" "

Steve
quelle
2
woah! Du hast meine +1
Am33d
16

Ein Sonderfall ist der Versuch, festzustellen, ob ein Boolescher Wert Null ist:

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

In diesem Fall wäre die Empfehlung zu verwenden .nil?

Alan H.
quelle
14

Nur eine kleine Anmerkung zur any?Empfehlung: Er hat Recht, dass es im Allgemeinen gleichbedeutend ist mit !empty?. Kehrt any?jedoch truezu einer Zeichenfolge mit nur Leerzeichen (ala " ") zurück.

Und natürlich auch den obigen Kommentar 1.9.

Davemyron
quelle
In Rails ist jede Zeichenfolge, die nur Leerzeichen enthält, "leer": "\ n \ r \ t" .blank? # => true
Lonny Eachus
13

Vergiss nicht, any?was allgemein ist !empty?. In Rails überprüfe ich normalerweise das Vorhandensein von etwas am Ende einer Anweisung mit if somethingoder verwende es unless somethingdann, blank?wo es benötigt wird, da es anscheinend überall funktioniert.


quelle
4
.irgendein? funktioniert nicht mit Strings in Ruby 1.9, wie .any? erfordert eine Aufzählung, und die Zeichenfolge # funktioniert in Ruby 1.9 nicht für sich.
Andrew Grimm
4
Vorsicht any?bei der Überprüfung der Nichtleere. Es gibt false zurück, wenn Sie ein Array von falschen Werten haben. Eine Möglichkeit, dies zu umgehen, besteht darin, einen immer zutreffenden Block zu übergeben : [nil, false].any?{ true }, der jedoch !empty?kürzer ist und Sie sich nicht an das seltsame Verhalten erinnern können.
Kelvin
12

nil?ist eine Standard-Ruby-Methode, die für alle Objekte aufgerufen werden kann und zurückgibt, truewenn das Objekt nil:

b = nil
b.nil? # => true

empty?ist eine Standard-Ruby-Methode, die für einige Objekte wie Strings, Arrays und Hashes aufgerufen werden kann und zurückgegeben wird, truewenn diese Objekte kein Element enthalten:

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

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

empty?kann nicht für nilObjekte aufgerufen werden.

blank?ist eine Rails-Methode, die sowohl für nilObjekte als auch für leere Objekte aufgerufen werden kann .

neha
quelle
7

Alle anderen haben gut erklärt, was der Unterschied ist.

Ich möchte Ruby On Rails hinzufügen, es ist besser, obj.blank?oder obj.present?anstelle von obj.nil?oder zu verwenden obj.empty?.

obj.blank?Griffe alle Arten nil, '', [], {}, und kehrt , truewenn Werte nicht zur Verfügung und kehrt sind , falsewenn Werte auf jede Art von Objekt zur Verfügung stehen.

Manish Shrivastava
quelle
5

exists?Mit dieser Methode kann überprüft werden, ob die Daten in der Datenbank vorhanden sind oder nicht. Es gibt entweder trueoder boolesche Werte zurück false.

Kelvin
quelle
Funktioniert nur in der Modellklasse!
Roger
4

Schienen 4

eine Alternative zu @ corban-brooks 'Array gotcha: blank?' um zu überprüfen, ob ein Array nur leere Werte enthält und als leer angesehen werden kann? wahr:

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

man könnte auch tun:

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

nil?kann für jedes Objekt verwendet werden. Es bestimmt, ob das Objekt einen Wert hat oder nicht, einschließlich 'leerer' Werte.

Zum Beispiel:

example = nil
example.nil?  # true

"".nil?  # false

Grundsätzlich nil?wird nur dann true zurückgegeben, wenn das Objekt tatsächlich gleich 'nil' ist.

empty?wird nur für Objekte aufgerufen, die als Sammlung betrachtet werden. Dazu gehören Zeichenfolgen (eine Sammlung von Zeichen), Hashes (eine Sammlung von Schlüssel / Wert-Paaren) und Arrays (eine Sammlung von beliebigen Objekten).empty?Gibt true zurück, wenn sich keine Elemente in der Sammlung befinden.

Zum Beispiel:

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

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

Beachte das empty? nil-Objekte nicht aufgerufen werden können, da nil-Objekte keine Sammlung sind und eine Ausnahme auslösen.

Beachten Sie auch, dass selbst wenn die Elemente in einer Sammlung leer sind, dies nicht bedeutet, dass eine Sammlung leer ist.

blank?ist im Grunde eine Kombination aus nil?und empty?Es ist nützlich, um Objekte zu überprüfen, von denen Sie annehmen, dass sie Sammlungen sind, könnte aber auch Null sein.

Chitra
quelle