Rails的HashWithIndifferentAccess
ruby 2.0 引入了keyword arguments,方法的参数可以这么声明
def foo(bar: 'default') puts bar end foo # => 'default' foo(bar: 'baz') # => 'baz'
在某些情况下,参数可能已经保存到了一个hash中的时候,也可以这么调用
params = {bar: 'baz'} foo(params) # => 'baz'
在rails中,请求传过来的参数都会变成HashWithIndifferentAccess,可以通过Symbol或者String作为key获取value
params = {bar: 'baz'}.with_indifferent_access params[:bar] # => 'baz' params['bar'] # => 'baz'
如果直接将HashWithIndifferentAccess作为参数传给keyword arguments的方法,是行不通的
params = {bar: 'baz'}.with_indifferent_access foo(params) # ArgumentError: wrong number of arguments (1 for 0)
这是因为HashWithIndifferentAccess中是以String作为key的,本质上和以下的错误是一样的
params = {'bar' => 'baz'} foo(params) # ArgumentError: wrong number of arguments (1 for 0)
所以需要将HashWithIndifferentAccess转换成以Symbol作为key
params = {bar: 'baz'}.with_indifferent_access foo(params.symbolize_keys) # 'baz'
有人提过相关的issue给rails和ruby
https://bugs.ruby-lang.org/issues/9731
rails/rails#14643
HashWithIndifferentAccess使用String作为key的原因之一是因为2.2之前的ruby版本是不能垃圾回收Symbol。