通常、RubyはHashのキーがSymbolかStringかを判別する
hash = { :key => 'sym', 'key' => 'str' }
p hash[:key]
# => 'sym'
p hash['key']
# => 'str'
しかし、Railsの、例えばcontrollerなどで使われるparams
ではこうはならない。SymbolとStringのどちらを指定しても同じ値が取得できる。
class SampleController < ApplicationController
def index
p params[:controller] # => 'sample'
p params['controller'] # => 'sample'
end
end
これはparamsがただのHashではなく、active_supportのHashWithIndifferentAccess
クラスを継承したクラスであるため(ActionController::Parameters)。
なのでこのクラスを使えばRailsのparamsみたいにキーがsymbolでもstringでも同じ値を取得することができるようになる。
Hashクラスに拡張された、with_indifferent_access
メソッドを呼び出して使った例が次のコード。
require 'active_support'
require 'active_support/core_ext'
hash = { :key => 'value' }.with_indifferent_access
p hash[:key]
# => 'value'
p hash['key']
# => 'value'
HashWithIndifferentAccess
クラスをnewして使うことも可能
require 'active_support'
require 'active_support/core_ext'
hash = ActiveSupport::HashWithIndifferentAccess.new(key: 'value')
p hash[:key]
# => 'value'
p hash['key']
# => 'value'
実装的には、HashWithIndifferentAccess#convert_key
を使って、keyがsymbolの場合に文字列化しているだけっぽかった。
def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end