18 Jun 2010

empty? nil? blank?とtrue false

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


empty? nil? blank?の違い


  1. # blank?はActivesupportのObjectクラスのメソッド  
  2. # p "".blank?   #=> undefined method `blank?' for "":String  
  3.   
  4. require 'rubygems'  
  5. require 'active_support'  
  6.   
  7. p ["", [], {}, nil, 0].collect{|v| v.nil?} #=>[false, false, false, true, false]  
  8.   
  9. p ["", [], {}, "\n""\t"].collect{|v| v.empty?} #=>[true, true, true, false, false]  
  10. # p 0.empty?    #=> undefined method `empty?' for 0:Fixnum  
  11. # p nil.empty?  #=> undefined method `empty?' for nil:NilClassp   
  12.   
  13. ["", [], {}, 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?の定義って
  1. def blank?  
  2.  self.nilor self.empty?  
  3. end  
かと思ってましたが、そういうわけでもないんですね。


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


例えば、
  1. [].instance_eval{ respond_to?(:blank?) } #=> false  
  2. [].blank? #=> undefined method `blank?' for []:Array  

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


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




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


さてTrue, Flseの方はと言いますと、
  1. >> ["", [], {}, nil, 0, "\n""\t"].collect{|v| if v then trueelse falseend}  
  2. => [truetruetruefalsetruetruetrue]  

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

.