Ruby のシンボル(続き)

昨日の記事の続き。

あれからいろいろ探し回ってみたらこんな記事が。
Lost-Season - Rubyのシンボル』のコメント欄より。

RailsではHashを拡張してkeyにstringとsymbolどちらを指定しても同じvalueが返されるようなクラスなども存在します。

なるほど。やはり Rails がうまくやってくれてたのか。


で、もう少しシンボルについて調べていたら、シンボルを使うことの意味について解説された記事を発見。
川o・-・)<2nd life - RubyのSymbol

まず使い道ですが、文字の定義を明確にしたいときに使うことが多いです。たとえばhashのkeyだったり、アクセサの引数で渡すインスタンス変数名だったり、alias_methodの引数で渡すメソッド名だったりと、文字に意味づけしたい時に使えます。このようなときにSymbolを使うことによって、ソースがすっきりして可視性が上がります。

また、symbolを使うと速度が向上します。これは、'a' と書くと毎回Stringの'a'を生成しコストが発生しますが、:aと書くと初回にしかコストが発生しません*1。比較も高速に行えます。

だそうです。なるほど。

で、同じ記事の後半には以下のように書いてある。

keyがsymbolかstringか解らなくて結局の所ソースを実際に確かめるケースが発生します。Railsではそれを取り除くために、active_supportで定義されているHashWithIndifferentAccessクラスを使い回避しています。

Rails でシンボルと String の変換をやってくれているのは ActiveSupport の HashWithIndifferentAccess というクラスとのこと。

さっそく調べてみるとindifferent_access.rb 内に conver_key というメソッドがあり

 def convert_key(key)
   key.kind_of?(Symbol) ? key.to_s : key
 end

として、シンボルなら文字列に変換、String ならそのままでキーの検索をしていた。なるほど。

というわけで昨日からの疑問が解決。うーん、奥が深い・・・