Rails 的 HashWithIndifferentAccess

NickWarm
Nickwarm Journey
Published in
4 min readJun 28, 2018

--

Photo by Andrew Ridley on Unsplash

我們先從 rails 的 parameter 開始談

我們常會用 params[:id] 來撈資料,但是為何 params 會有像是Ruby hash 的操作呢?

>> params
=> <ActionController::Parameters {"controller"=>"brands", "action"=>"show", "id"=>"icook"} permitted: false>
>> params[:id]
=> "icook"
>> params.class
=> ActionController::Parameters

透過 params.class 我們知道可以去查 strong parameter 的 source code 來追根究底,發現一層層 require 最後會連到 HashWithIndifferentAccess

  1. rails api: Action Controller Parameters
  2. rails/actionpack/lib/action_controller/metal/strong_parameters.rb
  3. strong parameter 的 initialize
  4. rails/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
  5. rails/activesupport/lib/active_support/hash_with_indifferent_access.rb

HashWithIndifferentAccess 就如同他的命名所示,key 無論是用 symbol 或是 string 來撈,都是沒有差別的 ( indifferent )

>> params[:id]
=> "icook"
>> params['id']
=> "icook"

就像 ruby hash 的 slice, strong parameter 所實作的 slice 也是出自 HashWithIndifferentAccessslice 。。

所以我們也可以像平常 ruby 用 slice 的寫法

>> params
=> <ActionController::Parameters {"controller"=>"brands", "action"=>"show", "id"=>"icook"} permitted: false>
>> params.slice(:controller, :id)
=> <ActionController::Parameters {"controller"=>"brands", "id"=>"icook"} permitted: false>
>> params.slice('controller', 'id')
=> <ActionController::Parameters {"controller"=>"brands", "id"=>"icook"} permitted: false>

最後讓我們回來看一下 HashWithIndifferentAccessdoc 或 initialize 的 source code 會發現

我們也可以傳一個普通的 ruby hash 給 HashWithIndifferentAccess.new 讓他轉生成強大的 HashWithIndifferentAccess instance ,然後這個 instance 就不用煩惱 key 用 symbol 或 string 了

注意:

ActiveSupport::HashWithIndifferentAccess 生出的 hash 不適合與 Ruby 的 Hash 生出的 hash 混著用,容易有預料之外的問題,i.e:

regular = Hash.new
regular[:one] = 1
regular[:two] = 2
regular # => {:one=>1, :two=>2}indifferent = HashWithIndifferentAccess.new
indifferent[:one] = "one"
regular.merge(indifferent)
# => {:one=>1, :two=>2, "one"=>"one", "two"=>"two"}

ref:http://jocellyn.cz/2014/05/03/hash-with-indifferent-access.html

相關文章

--

--

NickWarm
Nickwarm Journey

Rubyist。Nicholas aka Nick. Experienced in Ruby, Rails. I like to share the experiences what I learned.