Ruby và Rails có vài method check sự tồn tại giá trị hoặc trạng thái object. Ruby cung cấp #nil? và #empty?, ActiveSupport của Rails thêm #blank? và #present?. Tất cả hoạt động theo cách riêng và quan trọng phải biết từng method evaluate data như thế nào vì dùng sai có thể gây kết quả bất ngờ.
Bài này sẽ refresh kiến thức về các method này. Chúng ta sẽ (học lại) điều kiện pass/fail khi dùng từng method cũng như kiểu object mỗi method áp dụng được. Sẽ có cheat sheet tiện lợi ở cuối!
#nil?
#nil? là Ruby method trên class Object. Vì tất cả class kế thừa từ class này, #nil? dùng được trên mọi object. Trả về true cho nil (instance của NilClass) và false cho mọi thứ khác.
nil.nil? # => true
true.nil? # => false
5.nil? # => false
"".nil? # => false
[].nil? # => false
#empty?
#empty? dùng trên string, array, hash và set. Trả về true nếu instance object có length bằng 0.
Trên string, trả true cho empty string.
"".empty? # => true
Lưu ý whitespace character là character nên #empty? trên string chỉ chứa whitespace trả false. Vì vậy nó có thể không phải method tốt nhất validate text. Nếu chỉ dùng validate user input, có thể xử lý input chỉ chứa whitespace.
" ".empty? # => false
"\t\n".empty? # => false
Với array, hash, set, trả true nếu không có element.
[].empty? # => true
{}.empty? # => true
require 'set'
Set.new.empty? # => true
Khi #empty? dùng trên nil hoặc class không có method, raise NoMethodError. Vì vậy để dùng check data, phải thêm check đảm bảo chương trình không crash.
if !my_var.nil? && !my_var.empty?
# make use of my_var
end
Method tốt hơn là Rails #blank?, chúng ta xem ngay.
#blank?
#blank? là Rails method (trong ActiveSupport). Hoạt động trên mọi object.
Với string, trả true cho empty string và string chỉ chứa whitespace.
"".blank? # => true
" ".blank? # => true
"\n\t".blank? # => true
Với array, hash, set, hoạt động như #empty?, trả true nếu không có element.
[].blank? # => true
{}.blank? # => true
Set.new.blank? # => true
[nil].blank? # => false
["", ""].blank? # => false
person = {:firstName => "John", :lastName => "Doe"}
person.blank? # => false
Trả false cho true và true cho mọi điều kiện falsey (nil và false).
true.blank? # => false
false.blank? # => true
nil.blank? # => true
Như bạn thấy, tốt hơn dùng #blank? thay #empty? validate data vì nó không gây NoMethodError trên một số object (vì available cho tất cả object). Cũng không pass cho string chỉ chứa whitespace.
#present?
#present? cũng là Rails method. Làm ngược #blank?.
!my_var.blank? == my_var.present? # => true
Ví dụ:
"".present? # => false
" ".present? # => false
[].present? # => false
nil.present? # => false
true.present? # => true
false.present? # => false
{}.present? # => false
person = {:firstName => "John", :lastName => "Doe"}
person.present? # => true
5.present? # => true
Cũng tốt hơn #empty? validate cho cùng lý do #blank?.
Kết luận
Vì tên method dễ nhầm lẫn, đây là cheat sheet tiện để bookmark.
#nil? | #empty? | #blank? | #present? | |
|---|---|---|---|---|
5 | false | NoMethodError | false | true |
"" | false | true | true | false |
" " | false | false | true | false |
"\t\n" | false | false | true | false |
[] | false | true | true | false |
["a"] | false | false | false | true |
{} | false | true | true | false |
{a: "b"} | false | false | false | true |
Set.new | false | true | true | false |
nil | true | NoMethodError | true | false |
true | false | NoMethodError | false | true |
false | false | NoMethodError | true | false |
Như mọi thứ, lựa chọn giữa #nil?, #empty?, #blank?, #present? phụ thuộc tình huống. Check user có tên để gọi chẳng hạn, #present? phù hợp. Tuy nhiên #blank? và #present? trả boolean cho mọi object, có thể che bug bằng cách không raise error khi giá trị sai type.
Hy vọng chúng tôi refresh memory bạn về check giá trị trong Ruby. Nếu có câu hỏi hoặc comment, đừng ngần ngại drop line @AppSignal.