QA@IT

Ruby on Railsのblank?とempty?はどう使い分ければいい?

11228 PV

Ruby on Rails(Active Support)には、Ruby本体にない blank? というメソッドがありますが、 empty? と、どう使い分けるものでしょうか? 似たメソッドに nil? もありますが、どのオブジェクトに使えるのか、どう使うのかで、ちょっと混乱しています。

回答

@knsmrさん

おっしゃるとおりblank?present?はぬるぽ避けになって便利ではあるんですが、なるべく濫用を避け、Ruby標準のempty?any?none?等で間に合う場面では素直にそちらを使用するように心がけたいものです。
理由としては以下の2つが挙げられます。

  1. 明らかにArrayやHashのインスタンスしか取り得ない箇所で、empty?で済むはずなのにblank?と書かれていると、読み手はnilを考慮して敢えてそのように書かれているんだろうか、と深読みしてしまいます。同様に、nilかどうかを判定するためだけにblank?と書くのも悪手です。この場合nil?で充分ですし、falsyの判定だけならunless fooだけで間に合う場合も多いはずです。読者のことも考えて、必要十分なメソッドを選んで書かれているコードのほうが良いコードと言えます。

  2. スピード
    Ruby標準のempty?any?none?等を利用したほうがメソッド呼び出しの数が減って、実行速度が(ほんの少し)早くなります。

編集 履歴 (0)
  • なるほど。blank?が強力だからといって使い過ぎると、それを書いた意図や、コードの挙動について読み手の負担にかけることになるということですね。ありがとうございました! -

ActiveSupport 3.2 での blank? の大まかな挙動は以下の通りです:

  • nil か false なら true を返す
  • empty? に反応するオブジェクト (Array や Hash) の場合、空なら true を返す
  • 文字列の場合、長さが 0 または空白文字 (全角空白を含む) のみなら true を返す
  • それ以外の場合 false を返す

(参考: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb)

というわけで、「なんとなく空っぽいもの」であれば blank? だけで判定できるようになっています。逆に、例えば nil と空の配列、空文字列と空白文字のみの文字列を区別したいような場面では使えません。

一点注意しないといけないのが nil? の扱いです。blank? はオブジェクトが nil ならば true を返しますが、nil? をオーバーライドして true を返すようにしているオブジェクトでは false を返します。

>> o = Object.new
=> #<Object:0x000000048f32a8>
>> def o.nil?
>> true
>> end
=> nil
>> o.blank?
=> false

普段こんなコードを書くことはないと思いますが、ライブラリ内で使われているような場合に知らないとハマってしまうので気を付けてください。

(思い出せる範囲では Mongoid の AssociationProxy がこんな実装になっていたと思います)

編集 履歴 (0)
  • 何らかの理由でオブジェクトが nil の場合にも blank? を使っておけば、empty? と違って、NoMethodError: undefined method `empty?' for nil:NilClass と言われることもないということもあるのでしょうか? -
ウォッチ

この質問への回答やコメントをメールでお知らせします。