nil?, empty?, blank? trong Ruby on Rails - sự khác biệt thực sự là gì
Bài đăng này đã không được cập nhật trong 6 năm
nil?
- Cung cấp bởi Ruby
- Có thể sử dụng trên bất kỳ đối tượng nào
- Sẽ chỉ trả về
true
khi thực sự lànil
. Ví dụ:
nil.nil?
# => true
false.nil?
# => false
0.nil?
# => false
"".nil?
# => false
empty?
- Đây cũng là phương thức được cung cấp bởi Ruby
- Khác với
nil?
,empty?
chỉ sử dụng trên các đối tượng dạng tập hợp(collection) nhưHash
,Array
,Set
- Phương thức sẽ trả về
true
khi tập hợp không có phần tử nào Ví dụ:
[].empty?
# => true
{}.empty?
# => true
Set.new.empty?
# => true
- Tuy nhiên, phương thức này lại không bao gồm trong
Enumerable
, nguyên nhân là bởi không phải kiểuEnumerable
nào khi lặp cũng trả về giá trị. Để biết thêm thông tin có thể tham khảo tại đây Ví dụ:
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
fib.empty?
# NoMethodError: undefined method `empty?' for #<Enumerator:
- Bạn cũng có thể sử dụng
empty
với String (bởi vì String là mảng các ký tự). Ví dụ:
"".empty?
# => true
" ".empty?
# => false
- Vấn đề khi sử dụng
empty?
là bạn phải biết chắc chắn rằng kiểu của đối tượng bạn đang sử dụng làArray
haynil
. Nếu không biết trước điều này thì sử dụng nó sẽ không an toàn. Khi đó, bạn sẽ cần check điều kiệnnil?
trước. Ví dụ:
object = rand > 0.5 ? nil : array
object.empty? # can raise an exception
if !object.nil? && !object.empty? # doh...
# do something
end
Đó chính là lý do mà Rails định nghĩa phương thức blank?
trong ActiveSupport
.
blank?
- Cung cấp bởi Rails
nil
vàfalse
rõ ràng là blank còntrue
thì không.
class NilClass
def blank?
true
end
end
class FalseClass
def blank?
true
end
end
class TrueClass
# true.blank? # => false
def blank?
false
end
end
- Đối với
Array
vàHash
thì làblank?
khi chúngempty
. Điều này được thực hiện bằng cách sử dụngalias_method
như bên dưới:
class Array
# [].blank? # => true
# [1,2,3].blank? # => false
alias_method :blank?, :empty?
end
class Hash
# {}.blank? # => true
# { key: 'value' }.blank? # => false
alias_method :blank?, :empty?
end
- Khác với
String#empty?
chỉ kiểm tra trên độ dài của chuỗi thìString#blank?
còn kiểm tra thêm cả khoảng trắng. Ví dụ:
class String
BLANK_RE = /\A[[:space:]]*\z/
# A string is blank if it's empty or contains whitespaces only:
#
# ''.blank? # => true
# ' '.blank? # => true
# "\t\n\r".blank? # => true
# ' blah '.blank? # => false
#
# Unicode whitespace is supported:
#
# "\u00a0".blank? # => true
#
def blank?
# The regexp that matches blank strings is expensive. For the case of empty
# strings we can speed up this method (~3.5x) with an empty? call. The
# penalty for the rest of strings is marginal.
empty? || BLANK_RE.match?(self)
end
end
Điều này thuận tiện cho các ứng dụng web vì bạn thường muốn từ chối hoặc xử lý các chuỗi khác nhau chỉ chứa các khoảng trắng.
- Logic cho các class khác là nếu nó có cài đặt empty?
thì có thể sử dụng được blank?
. Điều này thật thú vị. Hãy nhìn cách cài đặt blank?
cho Object
ở dưới:
class Object
# An object is blank if it's false, empty, or a whitespace string.
# For example, +false+, '', ' ', +nil+, [], and {} are all blank.
#
# This simplifies
#
# !address || address.empty?
#
# to
#
# address.blank?
#
# @return [true, false]
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
Trong đó, !!empty?
chỉ sự phủ định nhân đôi, điều này rất hữu ích trong trường hợp giá trị là nil
, một chuỗi số hay các giá trị trả về là true, false khác. Bằng cách này giá trị trả về luôn được chuyển sang kiểu boolean:
!!true
# => true
!!false
# => false
!!nil
=> false
!!0
# => true
!!"abc"
# => true
- Number và Time sẽ không có blank?. Chúng sẽ luôn trả về false.
class Numeric #:nodoc:
# 1.blank? # => false
# 0.blank? # => false
def blank?
false
end
end
class Time #:nodoc:
# Time.now.blank? # => false
def blank?
false
end
end
present?
- Được cung cấp bởi Rails
present?
là phủ định củablank?
và có thể sử dụng ở bất cứ đâu
class Object
# An object is present if it's not blank.
def present?
!blank?
end
end
presence
- Cung cấp bởi Rails. Đôi khi bạn muốn viết một logic như:
params[:state] || params[:country] || 'US'
Nhưng bởi vì các tham số được nhập từ form nên đôi khi chúng có thể rỗng("") và khi đó chúng sẽ trả về ' '
thay vì 'US'
như mong muốn. Lúc này thì presence
rất hữu ích. Thay vì phải viết
state = params[:state] if params[:state].present?
country = params[:country] if params[:country].present?
region = state || country || 'US'
thì bạn có thể viết là
params[:state].presence || params[:country].presence || 'US'
- Phương thức này được cài đặt rất đơn giản:
class Object
def presence
self if present?
end
end
Vậy bạn nên sử dụng cái nào?
Nếu bạn làm việc với Rails, tôi khuyên bạn nên sử dụng prensent?
hoặc blank?
hoặc cả hai. Chúng có thể làm việc trên tất cả các đối tượng, làm việc trực quan tốt hơn và bạn không phải kiểm tra nil
ở bất kỳ đâu.
Tham khảo
Bài viết gốc: https://blog.arkency.com/2017/07/nil-empty-blank-ruby-rails-difference/
All rights reserved