18 Jun 2010

empty? nil? blank?とtrue false

Railsをやってると誰しもがありがたいと思うblank?。
- 他のempty?とnil?との使い分けは?
- ときどき、true, falseの条件とごっちゃになるし整理してみよう


empty? nil? blank?の違い



# blank?はActivesupportのObjectクラスのメソッド
# p "".blank? #=> undefined method `blank?' for "":String

require 'rubygems'
require 'active_support'

p ["", [], {}, nil, 0].collect{|v| v.nil?} #=>[false, false, false, true, false]

p ["", [], {}, "\n", "\t"].collect{|v| v.empty?} #=>[true, true, true, false, false]
# p 0.empty? #=> undefined method `empty?' for 0:Fixnum
# p nil.empty? #=> undefined method `empty?' for nil:NilClassp

["", [], {}, nil, 0, "\n", "\t"].collect{|v| v.blank?} #=>[true, true, true, true, false, true, true]


- nil?
 nilを判定するのにしか使えません

- empty?
 変数の初期値を判定するのに使える様です。"", [], {}はそれぞれString.new, Array.new, Hash.newと同じ値になります。Fixnum, NilClassにはnew methodはありません。

- blank?
 nilかempty?である場合を判定する場合に使えそうです。試してみた感じFixnumは常にfalseの様です。
blank?の定義って

def blank?
self.nil? or self.empty?
end
かと思ってましたが、そういうわけでもないんですね。


実際のところはこんな感じ

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 12
def blank?
respond_to?(:empty?) ? empty? : !self
end
respond_to?はRubyのObjectクラスのメソッドで、引数に取ったメソッドが応答するかどうか調べてくれるらしい。(ってつまりメソッドの存在チェック。)


例えば、

[].instance_eval{ respond_to?(:blank?) } #=> false
[].blank? #=> undefined method `blank?' for []:Array

って余計に説明わかりづらくした。すいません。


話を戻すと、blank?はempty?がある場合はそれを使って判定。そうじゃない場合はRubyの標準の判定の逆を返す。(ここの仕組みが僕はよく分かっていません。例えば if instance_of_objectとしたときどこで判定されるのか見つけられない。きっとライブラリでなく構文解析をやってるところに書いてあるかな)
respond_to?(:empty?) ? empty? : !self




何がTrue, Falseと判定されるか?


さてTrue, Flseの方はと言いますと、

>> ["", [], {}, nil, 0, "\n", "\t"].collect{|v| if v then true; else false; end}
=> [true, true, true, false, true, true, true]

nilだけがfalseと判定されます。

.