Cara memahami nil vs kosong vs kosong di Ruby

1129

Saya menemukan diri saya berulang kali mencari definisi yang jelas tentang perbedaan nil?, blank?dan empty?di Ruby on Rails. Inilah yang paling dekat dengan saya:

  • blank?objek adalah string palsu, kosong, atau spasi. Sebagai contoh, "", " ", nil, [], dan {}kosong.

  • nil? objek adalah instance dari NilClass.

  • empty?objek adalah kelas-spesifik, dan definisi bervariasi dari kelas ke kelas. String kosong jika tidak memiliki karakter, dan array kosong jika tidak mengandung item.

Apakah ada yang hilang, atau perbandingan yang lebih ketat yang bisa dibuat?

Arrel
sumber
26
Satu gotcha adalah array kosong yang mengembalikan false untuk present?. Yang karena blank?mengembalikan true untuk array kosong.
Kris
4
Satu hal yang menyenangkan adalah untuk melihat bahwa :nil?didefinisikan pada ::Kerneldan diganti pada ::NilClass, sementara :empty?diimplementasikan secara terpisah di banyak kelas (native pada ::String, ::Array, ::Hash, dan non-native di kelas-kelas lain seperti ::Setdari stdlib dan ::ActiveRecord::Relationdari rel). Jadi :nil?tersedia di semua subclass ::Objectdan juga di setiap kelas yang termasuk ::Kerneldengan sendirinya, di mana :empty?harus diterapkan atau dimasukkan secara khusus di kelas Anda.
ditulis ulang
Jika Anda mencoba memahami keseluruhan nilkonsep, mulailah dari sini .
totymedli
[1] pry(main)> [].blank? => true
Michael

Jawaban:

1437

.nil? dapat digunakan pada objek apa pun dan benar jika objek tersebut nihil.

.empty? dapat digunakan pada string, array dan hash dan mengembalikan true jika:

  • Panjang string == 0
  • Panjang array == 0
  • Panjang hasht == 0

Menjalankan .empty?sesuatu yang nihil akan melempar NoMethodError.

Di situlah .blank?masuk. Ini diterapkan oleh Rails dan akan beroperasi pada objek apa pun serta bekerja seperti .empty?pada string, array dan hash.

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

.blank? juga mengevaluasi true pada string yang tidak kosong tetapi hanya berisi spasi putih:

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

Rails juga menyediakan .present? , yang mengembalikan negasi .blank?.

Array Gotcha: blank?akan kembali falsebahkan jika semua elemen array kosong. Untuk menentukan kekosongan dalam hal ini, gunakan all?dengan blank?, misalnya:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 
Corban Brook
sumber
27
Seperti disebutkan dalam pertanyaan, beberapa string non-kosong dihitung sebagai kosong.
Andrew Grimm
1
Mengapa mereka tidak menimpa. Nihil ini? jika mereka bisa menambahkan .blank?
tillda
6
Juga:false.blank? == true
Shannon
2
Saya akan menyebutkan presence!
Marc-André Lafortune
2
Sebagai tambahan pada gotcha semua-kosong yang disebutkan Tom dalam jawabannya, perlu diketahui bahwa ini dapat menyebabkan masalah keamanan di mana penyerang dapat menggunakan kode tidak siap yang hanya memeriksa kecuali params.nil? atau kecuali params.blank ?, dan apakah penyebab banyak diskusi dan pekerjaan saat ini di Rails. Lihat di sini untuk informasi lebih lanjut: github.com/rails/rails/issues/13420
Houen
675

Saya membuat tabel yang berguna ini dengan semua kasus:

masukkan deskripsi gambar di sini

blank?, present?disediakan oleh Rails.

Julian Popov
sumber
57
Perlu dicatat bahwa kosong? dan hadir? hanya untuk Kereta Api. Mereka mengembalikan Pengecualian: NoMethodError di Ruby 2.0.0.
Lonny Eachus
17
Pertimbangkan untuk menambahkan any?jika Anda pernah memperbarui tabel.
Dennis
blank?dan present?bukan " Rails-only ", mereka secara otomatis disertakan oleh Rails tetapi dapat dengan mudah dimasukkan dalam kode non-Rails dengan menggunakan ekstensi Core ActiveSupport. Lihat stackoverflow.com/questions/4238867/…
the Tin Man
215

Cukup rentangkan meja Julian:

masukkan deskripsi gambar di sini

Ref: kosong? Kosong? Kosong? 傻傻 分不清楚

Sibevin Wang
sumber
1
@ Sibevin Wang, saya telah mengunduh tabel ini dan menggunakannya dalam beberapa jawaban saya menambahkan kredit untuk Anda. Semoga Anda tidak keberatan :) Salam untuk usaha yang luar biasa ini!
Lahiru
1
Enumerable#any?adalah vanilla Ruby, tidak boleh terdaftar di bawah "rails only"
daniero
1
@daniero Terima kasih atas pengingat Anda, tabel diperbarui.
Sibevin Wang
Jenis numerik juga memiliki .zero?dan.nonzero?
DaveMongoose
63

Kiat cepat: !obj.blank? == obj.present?

Dapat berguna / lebih mudah di mata dalam beberapa ekspresi

Alexander Malfait
sumber
apakah ada sesuatu yang setara dengan! obj.nil?
Kirk
present?adalah bagian dari active_support, periksa di sini tentang apa yang harus disertakan untuk mendapatkannya: stackoverflow.com/a/4648704/1569
Factor Mystic
2
@Kirk: !! obj sama dengan! Obj.nil?
Mohamed Hafez
4
@MohamedHafez Tidak bukan. !!false
Ajedi32
Agh, @ Ajedi32 tangkapan bagus! setara dengan satu pengecualian itu.
Mohamed Hafez
52

Salah satu perbedaan adalah bahwa .nil?dan .empty?adalah metode yang disediakan oleh bahasa pemrograman Ruby, sedangkan .blank?sesuatu ditambahkan oleh kerangka pengembangan web Rails.

Andrew Grimm
sumber
49

masukkan deskripsi gambar di sini

  • Semua yang nil?adablank?
  • Semua yang empty?adablank?
  • Tidak ada yang empty?adalahnil?
  • Tidak ada yang nil?adalahempty?

tl; dr - hanya gunakan blank?& present?kecuali Anda ingin membedakan antara ""dan" "

steve
sumber
2
Wow! Anda mendapatkan +1 saya
Am33d
16

Kasus khusus adalah ketika mencoba menilai apakah nilai boolean nol:

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

Dalam hal ini rekomendasi akan digunakan .nil?

Alan H
sumber
14

Hanya sedikit catatan tentang any?rekomendasi: Dia benar bahwa itu umumnya setara dengan !empty?. Namun, any?akan kembali trueke string hanya spasi putih (ala " ").

Dan tentu saja, lihat 1.9 komentar di atas juga.

davemyron
sumber
Di Rails, string apa pun yang berisi karakter spasi kosong adalah "kosong": "\ n \ r \ t" .blank? # => true
Lonny Eachus
13

Jangan lupa any?yang umumnya !empty?. Di Rails saya biasanya memeriksa keberadaan sesuatu di akhir pernyataan dengan if somethingatau unless somethingmenggunakan di blank?mana diperlukan karena tampaknya berfungsi di mana-mana.


sumber
4
.apa saja? tidak bekerja dengan string di ruby ​​1.9, seperti .any? membutuhkan enumerable, dan string # masing-masing dengan sendirinya tidak berfungsi di ruby ​​1.9.
Andrew Grimm
4
Berhati-hati any?dalam memeriksa ketidak-kekosongan. Ini mengembalikan false jika Anda memiliki array nilai-nilai palsu. Cara untuk menyiasatinya adalah dengan melewati blok yang selalu benar:, [nil, false].any?{ true }tetapi !empty?lebih pendek dan Anda tidak ingat perilaku anehnya.
Kelvin
12

nil?adalah metode standar Ruby yang dapat dipanggil pada semua objek dan kembali truejika objeknya adalah nil:

b = nil
b.nil? # => true

empty?adalah metode standar Ruby yang dapat dipanggil pada beberapa objek seperti Strings, Array dan Hash dan kembali truejika objek ini tidak mengandung elemen:

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

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

empty?tidak bisa dipanggil pada nilobjek.

blank?adalah metode Rails yang dapat dipanggil pada nilobjek maupun objek kosong.

neha
sumber
7

Semua orang telah menjelaskan dengan baik apa bedanya.

Saya ingin menambahkan di Ruby On Rails, lebih baik menggunakan obj.blank?atau obj.present?daripada obj.nil?atauobj.empty? .

obj.blank?menangani semua jenis nil, '', [], {}, dan kembali truejika nilai-nilai tidak tersedia dan kembali falsejika nilai-nilai yang tersedia pada setiap jenis objek.

Manish Shrivastava
sumber
5

exists?Metode dapat digunakan untuk memeriksa apakah data ada dalam database atau tidak. Ini mengembalikan nilai boolean baik trueatau false.

kelvin
sumber
Hanya bekerja pada kelas model!
Roger
4

Rel 4

alternatif untuk @ corban-brook 'Array gotcha: blank?' untuk memeriksa apakah array hanya memiliki nilai kosong dan dapat dianggap kosong? benar:

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

seseorang juga bisa melakukannya:

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

nil?dapat digunakan pada objek apa saja. Ini menentukan apakah objek memiliki nilai atau tidak, termasuk nilai 'kosong'.

Sebagai contoh:

example = nil
example.nil?  # true

"".nil?  # false

Pada dasarnya nil? hanya akan pernah mengembalikan true jika objek tersebut sebenarnya sama dengan 'nil'.

empty?hanya dipanggil pada objek yang dianggap koleksi. Ini termasuk hal-hal seperti string (kumpulan karakter), hash (kumpulan pasangan kunci / nilai) dan array (kumpulan objek yang berubah-ubah). empty?Mengembalikan nilai true adalah tidak ada item dalam koleksi.

Sebagai contoh:

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

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

Perhatikan bahwa empty?tidak dapat dipanggil pada objek nil karena objek nil bukan koleksi dan itu akan menimbulkan pengecualian.

Juga perhatikan bahwa meskipun item dalam koleksi kosong, itu tidak berarti koleksi kosong.

blank?pada dasarnya adalah kombinasi dari nil?dan empty?Ini berguna untuk memeriksa objek yang Anda anggap koleksi, tetapi bisa juga nol.

Chitra
sumber