はじめに
この業界に入り研修開けて半年、アウトプットも大切なのでテスト代わりにまとめようと思い、ちょこちょこ更新していきます。
一個一個確かめながら書くので長いし時間かかりそう。
指摘や改善点がありましたらよろしくお願いします。
実行環境
macOS 10.13.2
ruby 2.5.0
activesupport 5.1.4
pry
Active Support
blank? present?
require 'active_support'
require 'active_support/core_ext'
test = nil
test.blank? #=> true
test.present? #=> false
test.empty? #=> ”NoMethodError: undefined method `empty?' for nil:NilClass”
test = ""
test.blank? #=> true
test.present? =#> false
test = 0
test.blank? #=> false
test.present? #=> true
blank?とpresent?です。nil、falseとそれ以外を判定します。
blank?とempty?を混ぜて覚えてましたが、empty?はNilClassには使えません。
1/25追記
コメントで指摘されましたが、blank?は空白文字も空と判定しますので
empty?とは動作が違います。
自分の言い回しだとNilClassで使えるか否かのみに読み取れますね。ありがとうございます。
せっかくなのでもう少し深く掘り下げて説明しようと思います。
RailsGuidesの説明だと以下の通りです。
Railsアプリケーションは以下の値を空白(blank)とみなします。
nilとfalse
空白文字 (whitespace) だけで構成された文字列 (以下の注釈参照)
空欄の配列とハッシュ
その他、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
# An object is present if it's not blank.
#
# @return [true, false]
def present?
!blank?
end
まずはObjectClassです。
present?は!blank?というのが読み取れます。ソースにコメントで例を書いてるのがありがたいですね。
class NilClass
# +nil+ is blank:
#
# nil.blank? # => true
#
# @return [true]
def blank?
true
end
end
class FalseClass
# +false+ is blank:
#
# false.blank? # => true
#
# @return [true]
def blank?
true
end
end
class TrueClass
# +true+ is not blank:
#
# true.blank? # => false
#
# @return [false]
def blank?
false
end
end
次はNilClass、FalseClass、TrueClassの定義です。しっかりNilClassにも定義されています。
class Array
# An array is blank if it's empty:
#
# [].blank? # => true
# [1,2,3].blank? # => false
#
# @return [true, false]
alias_method :blank?, :empty?
end
class Hash
# A hash is blank if it's empty:
#
# {}.blank? # => true
# { key: 'value' }.blank? # => false
#
# @return [true, false]
alias_method :blank?, :empty?
end
ArrayとHashはempty?が呼ばれていますね。
class String
BLANK_RE = /\A[[:space:]]*\z/
ENCODED_BLANKS = Concurrent::Map.new do |h, enc|
h[enc] = Regexp.new(BLANK_RE.source.encode(enc), BLANK_RE.options | Regexp::FIXEDENCODING)
end
# 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
#
# @return [true, false]
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? ||
begin
BLANK_RE.match?(self)
rescue Encoding::CompatibilityError
ENCODED_BLANKS[self.encoding].match?(self)
end
end
end
指摘されたStringClassです。RailsGuidesにも注釈がありましたが、
文字列判定に[:space:]が使用されています。こちらで確認しましたらスペースやタブ、改行などが含まれるそうです。
それら以外がある場合はfalseになるようです。
class Numeric #:nodoc:
# No number is blank:
#
# 1.blank? # => false
# 0.blank? # => false
#
# @return [false]
def blank?
false
end
end
class Time #:nodoc:
# No Time is blank:
#
# Time.now.blank? # => false
#
# @return [false]
def blank?
false
end
end
最後はNumericClassとTimeClassです。数字と時間にはblankはないため必ずfalseが返ってくると書いてあります。
blank? present?のまとめ
- blank?は[:space:]に含まれる文字とnilとfalseに対してtrueを返す。
- present?はblank?の反対だよ。
- String#empty?はlengthが0の場合にtrueを返すよ!
presence
require 'active_support'
require 'active_support/core_ext'
test = ""
foo = test.presence || "こっちが入るよ"
p foo #=> "こっちが入るよ"
test.presence #=> nil
test = "今回はこっち"
foo = test.presence || "こっちが入るよ"
p foo #=> "今回はこっち"
presenceメソッドはガイドみて知りました。
定義元も見ましょう。
class Object
# Returns the receiver if it's present otherwise returns +nil+.
# <tt>object.presence</tt> is equivalent to
#
# object.present? ? object : nil
#
# For example, something like
#
# state = params[:state] if params[:state].present?
# country = params[:country] if params[:country].present?
# region = state || country || 'US'
#
# becomes
#
# region = params[:state].presence || params[:country].presence || 'US'
#
# @return [Object]
def presence
self if present?
end
end
コメントを見ればわかりますが、
present?をして
trueならそのオブジェクト自身、
falseならnilを返します。
使い方としては値が入っていればその値を使い、nilなら初期値を入れるみたいな使い方ですね。
# この書き方を
if foo.present?
bar = foo
else
bar = "初期値"
end
# 一行で書けてわかりやすい!
bar = foo.presence || "初期値"
presenceを覚えれば簡潔に書けそうです。
例にもあるようにparamsの代入でよく使えそうです。
presenceのまとめ
- 自身に対してpresent?をしてるよ
- trueなら自信を返すよ
- falseならnilを返すよ
- 初期値の代入とかで使えるよ
参考
Rails Guides Active Support コア拡張機能
Rubyのリファレンスみたいに書いてないのかな?と思ったらしっかり書いてありました。
Rails Guidesの情報量すごい
ブラケット表現 (Bracket Expression)
blank?で使われる[:space:]の説明