考虑下面的代码:

  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) }

hash4是"嵌套"哈希,即带有字符串键和类似"嵌套"哈希值的哈希.

Rails中哈希的"symbol_keys"方法让我们可以轻松地将字符串键转换为符号.但我正在寻找一种将所有键(主键加上hash4中所有散列的键)转换为符号的elegant种方法.

关键是要让自己从我(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

仅供参考:安装程序是Rails 3.2.17和Ruby 2.1.1

更新:

Rails的答案是hash4.deep_symbolize_keys<=5

Answer is JSON.parse(JSON[hash4], symbolize_names: true) for Rails > 5

推荐答案

有几种方法可以做到这一点

  1. deep_symbolize_keys method in Rails

    hash.deep_symbolize_keys!

  2. 正如@chrisgeeq所提到的,Rails 4提供了一个deep_transform_keys方法.

    hash.deep_transform_keys(&:to_sym)

    还有一个bang !版本来替换现有对象.

  3. 还有一种方法叫做with_indifferent_access.这允许您使用字符串或符号访问散列,比如params在控制器中的位置.这种方法没有一个爆炸对应物.

    hash = hash.with_indifferent_access

  4. 最后一个是使用JSON.parse.我个人不喜欢这样,因为你要做两个转换——从哈希到json,然后从json到哈希.

    JSON.parse(JSON[h], symbolize_names: true)

更新:

19年1月16日-添加更多选项并注意不推荐使用深\u符号\u键

2012年4月19日-删除不推荐的注释.只有方法中使用的实现是不推荐的,而不是方法本身.

Ruby-on-rails相关问答推荐

DELETE_IF和REJECT的意外行为!方法

mini_racer gem 0.8.0无法与Ruby 3.1.xBundle 安装

Rails 7中的Turbo流

包含字母和数字组合的正则表达式

如何从 New Relic 交易中获取 TraceId?

正确更新其他列的更新列

ViewModel 和 Controller 有什么区别?

ruby on rails 和 javascript 之间的时间转换反之亦然?

如何在两个日期之间生成随机日期和时间?

上传图片 Ruby on Rails

FactoryGirl + Faker - 为数据库种子数据中的每个对象生成相同的数据

Rails ActiveRecord 查询日期范围

Rails - 获取没有 GET 参数的当前 url

Ruby如何写入Tempfile

Ruby on Rails 错误无法加载此类文件 - 更少

使 rails 控制台输出更漂亮一点

在 Ruby on Rails 中循环对象属性

link_to 将参数与 url 一起发送并在目标页面上抓取它们

设计/Rails - 如何删除特定的 Flash 消息? (登录成功)

Rails:您已经激活了 rake 10.3.1,但您的 Gemfile 需要 rake 10.2.2 (Gem::LoadError)