【问题标题】:Update hash values with hash key使用哈希键更新哈希值
【发布时间】:2018-04-11 08:46:43
【问题描述】:

我遇到了一个我还没有找到有效解决方案的问题。

我有用于环境的 YAML 配置文件,我们称之为 development.yml。

此文件用于创建应更新的哈希:

data = YAML.load_file(File.join(Rails.root, 'config', 'environments', 'development.yml'))

我想要完成的是这些方面的事情。假设我们有一个排序元素

data['server']['test']['user']
data['server']['test']['password']

我想要的是:

data['server']['test']['user'] = #{Server.Test.User}
data['server']['test']['password'] = #{Server.Test.Password}

这个想法是为每个值创建一个占位符,该占位符是该值的动态键映射,一直到哈希的最后一级,并将该值替换为该值的映射,连接键。

抱歉,这并不能解决我的问题。位置data['server']['test']['user'] 将动态构建,通过将通过嵌套哈希的循环。我发现这样做的唯一方法是将哈希的当前迭代的键附加到字符串中。最后,我有一个类似"data['server']['test']['name']" 的字符串,我正在考虑将其转换为变量data['server']['test']['name'],然后将值分配给该变量#{Server.Test.Name}。阅读我的问题,我不确定这是否清楚,我希望这有助于澄清它。

输入样本:

api: 'active'
server:
  test:
    user: 'test'
    password: 'passwordfortest'
  prod:
    user: 'nottest'
    password: 'morecomplicatedthantest'

在这种情况下,最终的结果应该是这样更新这个yml文件:

api: #{Api}
server:
  test:
    user: #{Server.Test.User}
    password: #{Server.Test.Password}
  prod:
    user: #{Server.Prod.User}
    password: #{Server.Prod.Password}

这听起来很傻,但我想不出办法。

【问题讨论】:

  • 旁注: data['server']['host'] = #{Server.Host} 和 data['server']['host']['user'] = #{Server.Host.User} 不能同时使用。
  • 谢谢,@mudasobwa。我解决了我的问题。

标签: ruby hash


【解决方案1】:

我现在发布另一个答案,因为我知道这个问题是关于什么的。

使用Iteraptorgem:

require 'iteraptor'
require 'yaml'

# or load from file
yaml = <<-YAML.squish
api: 'active'
server:
  test:
    user: 'test'
    password: 'passwordfortest'
  prod:
    user: 'nottest'
    password: 'morecomplicatedthantest'
YAML

mapped =
  yaml.iteraptor.map(full_parent: true) do |parent, (k, _)|
    v = parent.map(&:capitalize).join('.')
    [k, "\#{#{v}}"]
  end

puts YAML.dump(mapped)
#⇒ ---
#  api: "#{Api}"
#  server:
#    test:
#      user: "#{Server.Test.User}"
#      password: "#{Server.Test.Password}"
#    prod:
#      user: "#{Server.Prod.User}"
#      password: "#{Server.Prod.Password}"

puts YAML.dump(mapped).delete('"')
#⇒ ---
#  api: #{Api}
#  server:
#    test:
#      user: #{Server.Test.User}
#      password: #{Server.Test.Password}
#    prod:
#      user: #{Server.Prod.User}
#      password: #{Server.Prod.Password}

【讨论】:

  • 对我来说,这对于一个解决方案来说已经足够了。关于您的解决方案只有一个问题:有没有一种方法可以在不添加 gem 的情况下实现这一目标?
  • @Harry 当然,这个 gem 是开源的;随意借用它需要的任何代码(我是这个 gem 的作者,所以我很自豪地授予你用它做任何你想做的事情的能力。)
【解决方案2】:

使用String#%:

input = %|
  data['server']['host']['name'] = %{server_host}
  data['server']['host']['user'] = %{server_host_user}
  data['server']['host']['password'] = %{server_host_password}
|
puts (
  input % {server_host: "Foo",
           server_host_user: "Bar",
           server_host_password: "Baz"})
#⇒ data['server']['host']['name'] = Foo
#  data['server']['host']['user'] = Bar
#  data['server']['host']['password'] = Baz

【讨论】:

  • 对不起,它不能解决我的问题。位置data['server']['host']['name'] 将通过一个遍历嵌套哈希的循环动态构建。我发现这样做的唯一方法是将哈希的最后一个键附加到字符串中。最后,我有一个字符串"data['server']['host']['name']",我正在考虑将其转换为变量data['server']['host']['name'],然后为该变量分配值#{Server.Host.Name}。阅读我的问题,我不确定这是否清楚,我希望这有助于澄清它。我已经更新了我的问题。
  • 请出示负责这些密钥的development.yml 部件。
  • 它没有变得更干净。您经常在哈希中提到 'host' 键,而您的样本没有任何痕迹。请花点时间清楚地说明输入是什么,预期输出是什么。对于发布的示例,无需动态创建任何哈希键,它们在输入和输出上没有区别。
  • 好的,让我在这里放一些细节。首先,问题中上面和下面的例子不是来自同一组。现在已经修好了。其次,如果您认为它们彼此没有区别,那么我不清楚我在问什么。 user: #{Server.Test.User} 是输出的一个例子,那里没有插值。 #{Server.Test.User} 是一个占位符,它将被另一个工具完全取代,最终将是user: 'test'。这不是问题的一部分,但这是这个脚本的全部原因。
【解决方案3】:

您不能将键值对添加到字符串中。

data['server']['host'] # => which results in a string

选项 1:

您可以将Server.Host 保存为哈希中的主机名

data['server']['host']['name'] = "#{Server.Host}"
data['server']['host']['user'] = "#{Server.Host.User}"
data['server']['host']['password'] = "#{Server.Host.Password}"

选项 2:

您可以使用 Host 作为键一步构建哈希。

data['server']['host'] = { "#{Server.Host}" => { 
                              'user' => "#{Server.Host.User}",
                              'password' => "#{Server.Host.Password}"
                            } 
                          }

【讨论】:

  • 对不起,我想我的问题不清楚。到该位置的地图将被动态构建,并且将在那里更新的值也将根据映射动态创建。
猜你喜欢
  • 2019-05-19
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2015-11-12
  • 2013-03-22
  • 1970-01-01
相关资源
最近更新 更多