Làm thế nào để hiểu nil so với trống so với trống trong Ruby


1129

Tôi thấy mình liên tục tìm kiếm một định nghĩa rõ ràng về sự khác biệt của nil?, blank?empty?trong Ruby on Rails. Đây là lần gần nhất tôi đến:

  • blank?các đối tượng là false, rỗng hoặc một chuỗi khoảng trắng. Ví dụ, "", " ", nil, [], và {}là trống.

  • nil? các đối tượng là các thể hiện của NilClass.

  • empty?các đối tượng là đặc thù của lớp và định nghĩa khác nhau giữa các lớp. Một chuỗi trống nếu nó không có ký tự và một mảng trống nếu nó không chứa các mục.

Có bất cứ điều gì còn thiếu, hoặc so sánh chặt chẽ hơn có thể được thực hiện?


26
Một gotcha là một mảng trống trả về false cho present?. Đó là bởi vì blank?trả về true cho một mảng trống.
Kris

4
Một điều tốt đẹp là để thấy rằng :nil?được định nghĩa trên ::Kernelvà ghi đè vào ::NilClass, trong khi :empty?được thực hiện riêng rẽ trên nhiều lớp (natively trên ::String, ::Array, ::Hash, và phi tự nhiên trên các lớp khác như ::Settừ stdlib và ::ActiveRecord::Relationtừ đường ray). Vì vậy, :nil?có sẵn trong tất cả các lớp con ::Objectvà cũng như trong mọi lớp bao gồm ::Kernelchính nó, nơi :empty?phải được thực hiện hoặc bao gồm cụ thể trong các lớp của bạn.
viết lại

Nếu bạn cố gắng để hiểu toàn bộ nilkhái niệm bắt đầu ở đây .
totymedli

[1] pry(main)> [].blank? => true
Michael

Câu trả lời:


1437

.nil? có thể được sử dụng trên bất kỳ đối tượng nào và là đúng nếu đối tượng là con số không.

.empty? có thể được sử dụng trên chuỗi, mảng và băm và trả về true nếu:

  • Độ dài chuỗi == 0
  • Độ dài mảng == 0
  • Độ dài băm == 0

Chạy .empty?trên một cái gì đó là không sẽ ném a NoMethodError.

Đó là nơi .blank?xuất hiện. Nó được Rails triển khai và sẽ hoạt động trên mọi đối tượng cũng như hoạt động như .empty?trên chuỗi, mảng và băm.

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

.blank? cũng đánh giá đúng trên các chuỗi không trống nhưng chỉ chứa khoảng trắng:

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

Rails cũng cung cấp .present? , trong đó trả về phủ định của .blank?.

Mảng gotcha: blank?sẽ trả về falsengay cả khi tất cả các phần tử của một mảng trống. Để xác định khoảng trống trong trường hợp này, ví dụ: sử dụng all?với blank?:

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

27
Như đã đề cập trong câu hỏi, một số chuỗi không trống được tính là trống.
Andrew Grimm

1
Tại sao họ không ghi đè lên .empty? nếu họ có thể thêm .blank?
Untilda

6
Ngoài ra:false.blank? == true
Shannon

2
Tôi muốn đề cập presence!
Marc-André Lafortune

2
Là một bổ sung cho gotcha toàn mảng trống mà Tom đang đề cập trong câu trả lời của mình, hãy lưu ý rằng điều này có thể dẫn đến các vấn đề bảo mật trong đó kẻ tấn công có thể sử dụng mã chưa chuẩn bị mà chỉ cần kiểm tra trừ khi params.nil? hoặc trừ khi params.blank?, và là nguyên nhân của nhiều cuộc thảo luận và công việc hiện tại trong Rails. Xem tại đây để biết thêm thông tin: github.com/rails/rails/issues/13420
Houen

675

Tôi đã tạo bảng hữu ích này với tất cả các trường hợp:

nhập mô tả hình ảnh ở đây

blank?, present?được cung cấp bởi Rails.


57
Cần lưu ý rằng trống? và hiện tại? là chỉ Rails. Họ trả về Ngoại lệ: NoMethodError trong Ruby 2.0.0.
Lonny Eachus

17
Xem xét thêm any?nếu bạn từng cập nhật bảng.
Dennis

blank?present?không phải là " Chỉ dành cho Rails ", chúng được Rails tự động đưa vào nhưng có thể dễ dàng được bao gồm trong mã không phải Rails bằng cách sử dụng các tiện ích mở rộng Core của ActiveSupport. Xem stackoverflow.com/questions/4238867/ Mạnh
Người đàn ông Tin

215

Chỉ cần mở rộng bảng của Julian:

nhập mô tả hình ảnh ở đây

Tham chiếu: trống? Trống? Nil? 傻傻


1
@Sibevin Wang, tôi đã tải xuống bảng này và sử dụng nó trong một số câu trả lời của tôi để thêm các khoản tín dụng cho bạn. Hy vọng bạn sẽ không phiền :) Kudos cho nỗ lực tuyệt vời này!
Lahiru

1
Enumerable#any?là vanilla Ruby, nó không nên được liệt kê trong "chỉ đường ray"
daniero

1
@daniero Cảm ơn bạn đã nhắc nhở, bảng được cập nhật.
Sibevin Wang

Các loại số cũng có .zero?.nonzero?
DaveMongoose

63

Mẹo nhanh: !obj.blank? == obj.present?

Có thể tiện dụng / dễ dàng hơn trên mắt trong một số biểu thức


Có cái gì tương đương với! obj.nil?
Kirk

present?là một phần của active_support, hãy kiểm tra ở đây về những gì cần bao gồm để có được nó: stackoverflow.com/a/4648704/1569
Nhân tố huyền bí

2
@Kirk: !! obj tương đương với! Obj.nil?
Mohamed Hafez

4
@MohamedHafez Không, không phải vậy. !!false
Ajedi32

Agh, @ Ajedi32 bắt tốt! tương đương với một ngoại lệ đó.
Mohamed Hafez

52

Một điểm khác biệt là .nil?.empty?là các phương thức được cung cấp bởi ngôn ngữ lập trình Ruby, trong khi đó .blank?là một thứ được thêm vào bởi khung phát triển web Rails.


49

nhập mô tả hình ảnh ở đây

  • Tất cả mọi thứ nil?blank?
  • Tất cả mọi thứ empty?blank?
  • Không có gì đó là empty?nil?
  • Không có gì đó là nil?empty?

tl; dr - chỉ sử dụng blank?& present?trừ khi bạn muốn phân biệt giữa """ "


2
ôi! bạn có +1 của tôi
Am33d

16

Một trường hợp đặc biệt là khi cố gắng đánh giá xem giá trị boolean có phải không:

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

Trong trường hợp này, khuyến nghị sẽ là sử dụng .nil?


14

Chỉ cần lưu ý một chút về any?khuyến nghị: Anh ấy nói đúng rằng nó thường tương đương với !empty?. Tuy nhiên, any?sẽ trở lại truemột chuỗi chỉ khoảng trắng (ala " ").

Và tất nhiên, xem bình luận 1.9 ở trên, quá.


Trong Rails, bất kỳ chuỗi nào chỉ chứa các ký tự khoảng trắng là "trống": "\ n \ r \ t" .blank? # => đúng
Lonny Eachus

13

Đừng quên any?đó là nói chung !empty?. Trong Rails tôi thường kiểm tra sự hiện diện của một cái gì đó ở cuối câu lệnh với if somethinghoặc unless somethingsau đó sử dụng blank?khi cần thiết vì nó dường như hoạt động ở mọi nơi.


4
.bất kì? không hoạt động với chuỗi trong ruby ​​1.9, như .any? yêu cầu vô số và chuỗi # mỗi chuỗi không hoạt động trong ruby ​​1.9.
Andrew Grimm

4
Cẩn thận về any?việc kiểm tra không trống rỗng. Nó trả về false nếu bạn có một mảng các giá trị giả. Một cách để khắc phục điều đó là vượt qua một khối luôn luôn đúng: [nil, false].any?{ true }nhưng !empty?ngắn hơn và bạn không nhớ hành vi kỳ lạ đó.
Kelvin

12

nil?là một phương thức Ruby tiêu chuẩn có thể được gọi trên tất cả các đối tượng và trả về truenếu đối tượng là nil:

b = nil
b.nil? # => true

empty?là một phương thức Ruby tiêu chuẩn có thể được gọi trên một số đối tượng như Chuỗi, Mảng và Băm và trả về truenếu các đối tượng này không chứa phần tử:

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

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

empty?không thể được gọi trên nilcác đối tượng.

blank?là một phương thức Rails có thể được gọi trên nilcác đối tượng cũng như các đối tượng trống.


7

Mọi người khác đã giải thích tốt sự khác biệt là gì.

Tôi muốn thêm vào Ruby On Rails, tốt hơn là sử dụng obj.blank?hoặc obj.present?thay vì obj.nil?hoặc obj.empty?.

obj.blank?xử lý tất cả các loại nil, '', [], {}, và lợi nhuận truenếu giá trị là không có sẵn và lợi nhuận falsenếu giá trị có sẵn trên bất kỳ loại đối tượng.


5

exists?phương pháp có thể được sử dụng để kiểm tra xem dữ liệu có tồn tại trong cơ sở dữ liệu hay không. Nó trả về giá trị boolean truehoặc false.


Chỉ hoạt động trên lớp mô hình!
Roger

4

Đường ray 4

một thay thế cho 'Array gotcha: @ trống?' của @ corban-brook để kiểm tra xem một mảng chỉ giữ các giá trị trống và có thể được coi là trống không? thật:

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

người ta cũng có thể làm:

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

3

nil?có thể được sử dụng trên bất kỳ đối tượng. Nó xác định xem đối tượng có bất kỳ giá trị nào hay không, bao gồm các giá trị 'trống'.

Ví dụ:

example = nil
example.nil?  # true

"".nil?  # false

Về cơ bản nil?sẽ chỉ trở về đúng nếu thực tế đối tượng bằng 'nil'.

empty?chỉ được gọi trên các đối tượng được coi là một bộ sưu tập. Điều này bao gồm những thứ như chuỗi (một tập hợp các ký tự), băm (một tập hợp các cặp khóa / giá trị) và mảng (một tập hợp các đối tượng tùy ý). empty?Trả về đúng là không có mục nào trong bộ sưu tập.

Ví dụ:

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

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

Lưu ý rằng empty?không thể được gọi trên các đối tượng không vì các đối tượng không phải là một bộ sưu tập và nó sẽ đưa ra một ngoại lệ.

Cũng lưu ý rằng ngay cả khi các mục trong bộ sưu tập trống, điều đó không có nghĩa là bộ sưu tập trống.

blank?về cơ bản là sự kết hợp nil?empty?Nó hữu ích để kiểm tra các đối tượng mà bạn cho là các bộ sưu tập, nhưng cũng có thể là không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.