В Ruby є відразу декілька схожих методів, що перевіряють чи має змінна значення. До того ж в Rails є декілька власних методів. В яких ситуаціях вони можуть бути корисні? Розберімо кожен з них.
nil?
-
Вбудований метод Ruby
-
Можна використовувати на будь-якій змінній.
-
Повертає
true
тільки дляnil
nil.nil?
# => true
false.nil?
# => false
0.nil?
# => false
"".nil?
# => false
empty?
-
Вбудований метод Ruby
-
Можна використовувати на колекціях:
Array
,Hash
,Set
і т.д. Повертаєtrue
, коли в колекції немає елементів.
[].empty?
# => true
{}.empty?
# => true
Set.new.empty?
# => true
- Але цей метод недоступний для
Enumerable
. Не всі ітеровані об'єкти, що повертають значення можуть знати мають вони елементи чи ні. Більше проenumerators
тут.
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:
- Також його можна застосовувати на рядках (тому що рядок це колекція символів)
" ".empty?
# => false
- Проблема
empty?
в тому, що вам потрібно знати яким класом ви оперуєте, аби не отримати помилку.
Ось тут в гру вступає Rails з розширенням ActiveSupport та методом blank?
.
blank?
-
Метод з Rails
-
nil
таfalse
, очевидно, вважаються пустими.
class NilClass
def blank?
true
end
end
class FalseClass
def blank?
true
end
end
-
true
— навпаки
class TrueClass
# true.blank? # => false
def blank?
false
end
end
-
Array
таHash
будутьblank?
якщо вониempty?
. Це реалізовано за допомогоюalias_method
. Ви можете спитати: «а як жеSet
?». Я відповім, але трохи згодом.
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
- Поведінка
String#blank?
трохи відрізняється відempty?
, тепер якщо рядок складається з пробілів та невидимих символів, він все одноblank?
.
class String
BLANK_RE = /\\A[[:space:]]*\\z/
#
# ''.blank? # => true
# ' '.blank? # => true
# "\ \
\
".blank? # => true
# ' blah '.blank? # => false
#
# Юнікодівські пробіли також підтримуються
#
# "\\u00a0".blank? # => true
#
def blank?
empty? || BLANK_RE.match?(self)
end
end
Це досить зручно для веб-додатків, адже в більшості випадків вам потрібен рядок з текстом, а не пробілами.
- Для решти класів цей метод ідентичний
empty?
. Цікаво, що там же і знаходиться документація методу.
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
Ви можете без проблем реалізувати цей метод для власного класу.
class Car
def initialize
@passengers = []
end
def enter(passenger)
@passengers << passenger
end
def empty?
@passengers.empty?
end
def run
# ...
end
end
car = Car.new
car.blank?
# => true
car.enter("robert")
car.blank?
# => false
- Числа та час не можуть бути пустими. Чесно кажучи, я не здогадуюсь чому ці методи реалізовані окремо і чому недостатньо реалізації в
Object
. Можливо, для того щоб зайвий раз не перевіряти наявністьempty?
, якого немає.
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?
-
Метод з Rails
-
present?
це просто інвертованийblank?
і може бути використаний для чого завгодно.
class Object
def present?
!blank?
end
end
presence
Цей метод теж з Rails. Іноді вам потрібно писати ось таку логіку:
params[:state] || params[:country] || 'US'
Але в більшості випадків параметри приходять з форми, тому можуть бути й пустими (або складатися з пробілів), і ви отримаєте ''
замість 'US'
. Тут потрібен presence
. Замість
state = params[:state] if params[:state].present?
country = params[:country] if params[:country].present?
region = state || country || 'US'
Ви пишете
params[:state].presence || params[:country].presence || 'US'
Його реалізація дуже проста!
class Object
def presence
self if present?
end
end
Так що ж мені використовувати?!
Якщо ви працюєте з Rails, я рекомендую використовувати present?
та/або blank?
. Вони доступні для всіх об'єктів, працюють інтуїтивно-зрозуміло і вам більше не потрібно вручну перевіряти на nil
.
Ще немає коментарів