避免在ruby中进行深度哈希查询

时间:2013-08-12 09:23:36

标签: ruby

如何整理在ruby中设置和请求深度哈希值的代码?

例如,假设我有这样的哈希:

  hash = {
    user_settings: {
      notifications: {
        overdue_tasks: { enabled: true, duration: 30 },
        created_overdue_tasks: { enabled: true, duration: 30 } 
      }
    }
  }

如何避免编写像这样的脆弱访问代码:

  hash[:user_settings][:notifications][:overdue_tasks][:duration] = 5

此外,是否存在递归symbolize_keys,它将象征所有键而不仅仅是顶层?

2 个答案:

答案 0 :(得分:1)

我不知道如何减少代码来获取所需的键/值,但我有一个建议是通过命名使你的哈希变为普通。

怎么样

hash = {
  user_settings: {
    overdue_task_notification_enabled:  true,
    overdue_task_notification_duration: 30,
    created_overdue_tasks_enabled:      true,
    created_overdue_tasks_duration:     30 
  } 
}

然后像

一样抓取它
hash[:user_settings][:created_overdue_tasks_duration]

我认为这种安排对于同行和用户来说更容易理解。

答案 1 :(得分:0)

在博客的帮助下: - Ruby Nested Hash - Deep Fetch - Returning a (Default) Value for a Key That Does Not Exist in a Nested Hash

class Hash
 def deep_fetch(key, default = nil)
   default = yield if block_given?
   (deep_find(key) or default) or raise KeyError.new("key not found: #{key}")
 end

 def deep_find(key)
    key?(key) ? self[key] : self.values.inject(nil) {|memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
  end
end


hash = {
    user_settings: {
      notifications: {
        overdue_tasks: { enabled: true, duration: 30 },
        created_overdue_tasks: { enabled: true, duration: 30 } 
      }
    }
  }

p hash.deep_fetch(:duration)
# >> 30