Harry
Harry

Reputation: 115

Update hash values with hash key

I'm facing a problem that I couldn't find a working solution yet.

I have my YAML config file for the environment, let's call it development.yml.

This file is used to create the hash that should be updated:

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

What I'm trying to accomplish is something along these lines. Let's suppose we have an element of the sort

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

What I want to have is:

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

The idea is to create a placeholder for each value that is the key mapping for that value dynamically, going until the last level of the hash and replacing the value with the mapping to this value, concatenating the keys.

Sorry, it doesn't solve my problem. The location data['server']['test']['user'] will be built dynamically, via a loop that will go through a nested Hash. The only way I found to do it was to append to the string the key for the current iteration of the Hash. At the end, I have a string like "data['server']['test']['name']", which I was thinking on converting to a variable data['server']['test']['name'] and then assigning to this variable the value #{Server.Test.Name}. Reading my question I'm not sure if this is clear, I hope this helps to clarify it.

Input sample:

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

In this case, the final result should be to update this yml file in this way:

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

It sounds silly, but I couldn't figure out a way to do it.

Upvotes: 0

Views: 516

Answers (3)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

I am posting another answer now since I realize what the question is all about.

Use Iteraptor gem:

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}

Upvotes: 1

Ashik Salman
Ashik Salman

Reputation: 1879

You can not add key-value pair to a string.

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

Option 1:

You can either save Server.Host as host name in the hash

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

Option 2:

You can construct the hash in a single step with Host as key.

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

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Use 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

Upvotes: 1

Related Questions