Railsの便利さを支えるActiveSupport。特にcore_extは単体で使うことも多いと思います。
基本的な機能ながら、バージョンごとに地味に機能修正が行われているので、わかりやすいものを2個取り上げてみました。
3.2で挙動が変わったblank?
blank?はご存じ、「空ならtrueを返す」便利メソッドです。
- blank?
- オブジェクトが空ならtrueを、そうでなければfalseを返す
- present?
- !blank?を返す
- presence
- blank?ならnilを、そうでなければselfを返す
blank?は基本的に以下のような仕組みです。
- empty?が定義されているとき: empty?を呼び出す
- empty?が定義されていないとき: !selfを返す
たとえば[]
にはempty?があるので、空配列はblank?がtrueになります。
nil
にはempty?がないので、!selfを評価した結果blank?はtrueになります。
Object.new
にはempty?がないので、!selfを評価した結果blank?はfalseになります。
実際にはArrayやNilClassなどには高速化のため別定義がしてあります。
ここで、Stringだけは違うルールでblank?が個別定義されているので注意が必要です。
Stringにはempty?が存在しますが、これは空文字であるかどうかを調べるメソッドです。
String#blank?はこれを使わず、「空白文字は空と見なす」として動作します。
この「空白文字」の定義がバージョンによって異なります。
# ActiveSupport 3.1.0
def blank?
self !~ /\S/
end
# ActiveSupport 3.2.0
NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]!
def blank?
# 1.8 does not takes [:space:] properly
if encoding_aware?
self !~ /[^[:space:]]/
else
self !~ NON_WHITESPACE_REGEXP
end
end
# ActiveSupport 4.0.0
def blank?
self !~ /[^[:space:]]/
end
3.1までは/\S/
が含まれていれば「空ではない」と見なされました。
つまり、「半角スペース」「タブ」「CR」「LF」の4文字以外は空白でないとされ、全角スペースは有効な文字とされていました。
3.2以降では[:space:]というPOSIX文字クラスに変更されています。
この文字クラスには全角スペースなども含まれるため、全角スペースのみの文字列にblank?を実行すると、
- 3.1まで: false
- 3.2から: true
という結果になります。
ちなみに[:space:]文字クラスの詳細は、RubyDocによると鬼車を参照しろと書いてあります。
http://www.geocities.jp/kosako3/oniguruma/doc/RE.txtによると、厳密には以下の文字になっています(Unicodeの場合)。
Space_Separator | Line_Separator | Paragraph_Separator |
0009 | 000A | 000B | 000C | 000D | 0085
Space_SeparatorはUnicodeのZsカテゴリ、Line_SeparatorはZlカテゴリU+2028だけ)、Paragraph_SeparatorはZpカテゴリ(U+2029だけ)です。
Unicodeで規定されている空白文字はすべてblank?になるようになっています。
4.0で挙動が変わったtry
基本メソッドtryも、4.0で挙動が変わりました。
# ActiveSupport 3.2.0
def try(*a, &b)
if a.empty? && block_given?
yield self
else
__send__(*a, &b)
end
end
# ActiveSupport 4.0.0
def try(*a, &b)
if a.empty? && block_given?
yield self
else
public_send(*a, &b) if respond_to?(a.first)
end
end
def try!(*a, &b)
if a.empty? && block_given?
yield self
else
public_send(*a, &b)
end
end
主な違いは2点です。
- sendがpublic_sendになった
- 直接呼び出すのと対称性が高まりました。privateメソッドを呼び出せることを期待していたコードは動かなくなります。
- respond_to?チェックをするようになった
- 従来のtryはtry!になり、tryではrespond_to?チェックが事前に実行されます。4.0のtryでは、存在しないメソッドを指定してもNoMethodErrorは発生せず、何もしません。
まとめ
Ruby界隈は良くも悪くも進歩と仕様変更が早いので、常に最新ウォッチが大事ですね。
更新情報はCHANGELOGをブックマークに入れておくのがたぶん手っ取り早いと思います。幸いテストがしっかりしているので、挙動が分からなければそちらを見ればOKです。
あと、Rails以外でRubyを使うときも、必ずgemはbundleで管理し、Gemfile.lockをリポジトリに入れておく方が良いと思います。