Nil? .empty? .blank? và .present? trong ROR
.blank? và .present? là những hàm thường xuyên sử dụng trong Rails. Sự tiện dụng là lí do những hàm này được dùng thường xuyên. Trước hết: .nil? và .empty? là hàm của Ruby .blank và .present? là các hàm được thêm trong Rails .nil? Theo Ruby doc thì: .nil? là một hàm của Object, nên tất cả các ...
.blank? và .present? là những hàm thường xuyên sử dụng trong Rails. Sự tiện dụng là lí do những hàm này được dùng thường xuyên. Trước hết: .nil? và .empty? là hàm của Ruby .blank và .present? là các hàm được thêm trong Rails .nil? Theo Ruby doc thì: .nil? là một hàm của Object, nên tất cả các object kế thừa từ Object mặc định đều có hàm nil? chỉ có nil object trả về true khi gọi nil?
nil.nil? # => true "".nil? # => false 4.nil? # => false Object.new.nil? # => false BasicObject.new.nil? # NoMethodError: undefined method `nil?' for #<BasicObject:0x0000000b794b30> from (pry):72:in `<main>'
.empty?
.empty? là function có sẵn của String, Array, Hash
Hiểu một cách đơn giản thì .empty? sẽ trả về true nếu:
string.length == 0 array.length == 0 hash.length == 0 Như vậy,
"".empty? # => true [].empty? # => true {}.empty? # => true " ".empty? # => false [nil].empty? # => false
.blank?
.blank? là một hàm rất thú vị của Rails, cũng như được sử dụng rất thường xuyên (cùng với .present?)
Theo như mô tả trong source code: một object được coi là blank nếu như nó false, empty hoặc là 1 chuỗi chỉ gồm các khoảng trắng.
Điều này cho phép ta dự đoán:
# những object dưới đây khi gọi `.blank?` sẽ trả về true vì chúng `empty` [].blank? # => true {}.blank? # => true "".blank? # => true # những object dưới đây khi gọi `.blank?` sẽ trả về true vì chúng `false` false.blank? # => true nil.blank? # => true # những object dưới đây khi gọi `.blank?` sẽ trả về true vì chúng là chuỗi chỉ có khoảng trắng " ".blank? # => true "s".blank? # => true # như vậy, những object dưới đây nên trả về false khi gọi `.blank?` true.blank? # => false 5.blank? # => false
Hãy cùng xem Rails định nghĩa .blank? ra sao (sao chép từ mã nguồn của Rails, đã lược bỏ chú thích):
class Object def blank? respond_to?(:empty?) ? !!empty? : !self end end class NilClass def blank? true end end class FalseClass def blank? true end end class TrueClass def blank? false end end class Array alias_method :blank?, :empty? end class Hash alias_method :blank?, :empty? end class String BLANK_RE = /A[[:space:]]*z/ def blank? BLANK_RE === self end end class Numeric def blank? false end end
Quên đi định nghĩa của .blank? trong lớp Object, xem phần còn lại ta sẽ thấy với Array và Hash thì .blank? chẳng qua là alias method của .empty?. Còn trong các lớp NilClass, FalseClass thì .blank? trực tiếp trả về false, trong các lớp TrueClass, Numeric thì .blank? trực tiếp trả về true.
Với lớp String, do có nhiều loại kí tự khoảng trắng (như space, tab) nên Rails sử dụng regex /[[:space:]]/ từ Ruby (xem Regexp). Điều này có nghĩa rằng tất cả các loại kí tự được Ruby xem là khoảng trắng sẽ được dùng cho việc xác định một chuỗi có gồm toàn khoảng trắng hay không, thể hiện qua ví dụ dưới đây:
# chuỗi này chỉ bao gồm toàn các kí tự khoảng trắng " s u00a0".blank? # => true
Vậy, như phần trên đã nói chỉ có Array, Hash và String có .empty?, trong khi .blank? trong các lớp trên đều đã bị khai báo đè lên trên khai báo của Object. Vậy tại sao .blank? trong Object vẫn được khai báo như sau:
class Object def blank? respond_to?(:empty?) ? !!empty? : !self end end
Việc tìm hiểu ý nghĩa của đoạn mã này phụ thuộc vào bạn, mình sẽ tạm dừng câu chuyện về .blank? tại đây.
.present?
Nếu 1 object không blank, vậy nó present.
# An object is present if it's not blank. # # @return [true, false] def present? !blank? end
Như vậy không có gì nhiều để nói về .present? nữa, tuy nhiên có một hàm có liên quan mật thiết đến .present? mà chúng ta cũng rất hay sử dụng, đó là .presence
def presence self if present? end
Với định nghĩa này ta có thể suy ra rằng .presence sẽ trả về object gọi nó nếu object đó present, còn không sẽ trả về nil.
Một ví dụ cho .presence:
s = " " || "default" # => " " s = " ".presence || "default" # => "default"
Kết luận
Việc hiểu bản chất của các hàm .nil?, empty?, .blank? và present? cho phép bạn thấy được sự khác nhau, cũng như hoàn cảnh mà bạn nên áp dụng từng hàm, giúp cho các đoạn mã của bạn rõ ràng hơn.