SHS*_*SHS 47 ruby hash ruby-on-rails dry
请考虑以下代码:
hash1 = {"one" => 1, "two" => 2, "three" => 3}
hash2 = hash1.reduce({}){ |h, (k,v)| h.merge(k => hash1) }
hash3 = hash2.reduce({}){ |h, (k,v)| h.merge(k => hash2) }
hash4 = hash3.reduce({}){ |h, (k,v)| h.merge(k => hash3) }
Run Code Online (Sandbox Code Playgroud)
hash4是一个'嵌套'哈希,即带有字符串键的散列和类似的'嵌套'哈希值.
Hails in Rails的'symbolize_keys'方法让我们可以轻松地将字符串键转换为符号.但我正在寻找一种优雅的方法将所有键(主键加上hash4中所有哈希的键)转换为符号.
重点是从我的(imo)丑陋的解决方案中解脱出来:
class Hash
def symbolize_keys_and_hash_values
symbolize_keys.reduce({}) do |h, (k,v)|
new_val = v.is_a?(Hash) ? v.symbolize_keys_and_hash_values : v
h.merge({k => new_val})
end
end
end
hash4.symbolize_keys_and_hash_values #=> desired result
Run Code Online (Sandbox Code Playgroud)
仅供参考:安装程序是Rails 3.2.17和Ruby 2.1.1
更新:
答案是hash4.deep_symbolize_keys针对Rails <= 5.0
答案是JSON.parse(JSON[hash4], symbolize_names: true)针对Rails> 5
jvn*_*ill 97
有几种方法可以做到这一点
deep_symbolize_keysRails中有一个方法,但Rails 5.1中不推荐这样做
hash.deep_symbolize_keys!
正如@chrisgeeq所提到的,deep_transform_keysRails 4提供了一种方法.
hash.deep_transform_keys(&:to_sym)
还有一个爆炸!版本来替换现有对象.
还有另一种方法叫做with_indifferent_access.这允许您使用字符串或符号(如params控制器中的方式)访问哈希.这种方法没有爆炸对应物.
hash = hash.with_indifferent_access
最后一个是使用JSON.parse.我个人不喜欢这个,因为你正在进行2次转换 - 哈希到json然后json到哈希.
JSON.parse(JSON[h], symbolize_names: true)
更新:
16/01/19 - 添加更多选项并注意deep_symbolize_keys的弃用
Mik*_*ski 25
您不能将此方法用于params或任何其他任何实例ActionController::Parameters,因为deep_symbolize_keys出于安全原因,Rails 5.0+中的方法已被弃用,并且将在Rails 5.1+中删除,因为ActionController::Parameters不再继承Hash
所以@Uri Agassi的这种方法似乎是普遍的方法.
JSON.parse(JSON[h], symbolize_names: true)
Run Code Online (Sandbox Code Playgroud)
但是,Rails Hash对象仍然拥有它.
所以选项是:
如果你不使用Rails或只是不关心:
JSON.parse(JSON[h], symbolize_names: true)
Run Code Online (Sandbox Code Playgroud)使用Rails和ActionController ::参数:
params.to_unsafe_h.deep_symbolize_keys
Run Code Online (Sandbox Code Playgroud)使用Rails和普通哈希
h.deep_symbolize_keys
Run Code Online (Sandbox Code Playgroud)在rails中,您可以创建HashWithIndifferentAccess类.创建此类的实例,将您的哈希传递给它的构造函数,然后使用符号或字符串的键(如Controller的Actions的参数)访问它:
hash = {'a' => {'b' => [{c: 3}]}}
hash = hash.with_indifferent_access
# equal to:
# hash = ActiveSupport::HashWithIndifferentAccess.new(hash)
hash[:a][:b][0][:c]
=> 3
Run Code Online (Sandbox Code Playgroud)