Edited at

HashのキーがSymbolでもStringでも値を取得する

More than 3 years have passed since last update.

通常、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)。

HashWithIndifferentAccessクラス

なのでこのクラスを使えばRailsのparamsみたいにキーがsymbolでもstringでも同じ値を取得することができるようになる。

Hashクラスに拡張された、with_indifferent_accessメソッドを呼び出して使った例が次のコード。

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