我阅读了一些关于Yaml或yml文件格式的快速教程。我制作了一个yaml文档来表示我的数据。我看到了一些ruby教程,告诉你如何用ruby提取yaml。不幸的是,他们只是打印整个数据或只是键和值。它不符合我的需要。请帮忙。
yaml文件 -
dev:
game1:
server1:
url: 'dev-game1-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game1-a-srv02.gamer.com'
log-path: '/srv/logs'
game2:
server1:
url: 'dev-game2-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game2-b-srv02.gamer.com'
log-path: '/srv/logs'
server3:
url: 'dev-game2-b-srv01.gamer.com'
log-path: '/srv/logs'
prod:
etc....
如何使用ruby代码选择dev,game2,server 3,url?
使用下面的代码,我得到一个例外 -
require 'yaml'
def server_info
path = 'C:\Code\demo-srv.yml'
yml = YAML::load(File.open(path))
game2 = yml['dev']['game2']
game2.each{|server|
if server['server3']
puts server['server3']['url']
end
}
end
server_info
错误 -
server.rb:8:in `[]': can't convert String into Integer (TypeError)
from server.rb:8:in `server_info'
from server.rb:7:in `each'
from server.rb:7:in `server_info'
from server.rb:14
答案 0 :(得分:5)
您是否定义了yaml-data,或者您只是现有yaml文件的使用者?
如果您定义了它,我会用Hash替换服务器数组(请参阅服务器名称前缺少的-
):
dev:
game1:
server1:
url: 'dev-game1-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game1-a-srv02.gamer.com'
log-path: '/srv/logs'
game2:
server1:
url: 'dev-game2-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game2-b-srv02.gamer.com'
log-path: '/srv/logs'
server3:
url: 'dev-game2-b-srv01.gamer.com'
log-path: '/srv/logs'
然后你可以尝试yml['dev']['game2']['server3']['url']
。
注意:没有检查丢失/错误的数据。如果game2
的条目遗漏,则此代码将引发异常。
所以,也许你应该做像
这样的事情if yml['dev'] and yml['dev'].kind_of?(Hash)
if yml['dev']['game2'] and ....
...
else
puts "No dev-branch defined"
end
否则你可以尝试类似的东西:
def server_info
yml = YAML::load(DATA)
yml['dev']['game2'].each{|server|
if server['server3']
p server['server3']['url']
end
}
end
注意(两种解决方案):
没有检查丢失/错误的数据。此处检查server['server3']
的存在。对于实际代码,您还应检查是否存在dev
和game2
数据。
编辑后继续回答:
如果您有一个数组但是期望散列并且您尝试使用字符串访问数组元素,则通常会抛出错误convert String into Integer
。
您可以尝试以下代码。有两个变化:
server
的输出 - 你会看到它是一个数组,没有哈希。第9 + 10行:数组由两个元素检查并使用(通过#first和#last)
require 'yaml'
def server_info
path = 'C:\Code\demo-srv.yml'
#~ yml = YAML::load(File.open(path))
yml = YAML::load(DATA)
game2 = yml['dev']['game2']
game2.each{|server|
p server #-> you get an array
if server.first == 'server3'
puts server.last['url']
end
}
end
server_info
文件 -
dev:
game1:
server1:
url: 'dev-game1-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game1-a-srv02.gamer.com'
log-path: '/srv/logs'
game2:
server1:
url: 'dev-game2-a-srv01.gamer.com'
log-path: '/srv/logs'
server2:
url: 'dev-game2-b-srv02.gamer.com'
log-path: '/srv/logs'
server3:
url: 'dev-game2-b-srv01.gamer.com'
log-path: '/srv/logs'
答案 1 :(得分:1)
我不知道为什么,yml['dev']['game2']
=>
[{"server1"=>{"url"=>"dev-game2-a-srv01.gamer.com", "log-path"=>"/srv/logs"}},
{"server2"=>{"url"=>"dev-game2-b-srv02.gamer.com", "log-path"=>"/srv/logs"}},
{"server3"=>{"url"=>"dev-game2-b-srv01.gamer.com", "log-path"=>"/srv/logs"}}]
所以你必须使用这个数组上的find来获得密钥。
require 'yaml'
# require 'pry'
def server3_url
yml = YAML::load(File.read('yaml.yml'))
# binding.pry
begin
yml['dev']['game2'].find{|x| x['server3']}['server3']['url']
rescue
end
end
puts server3_url
如果找不到密钥,server3_url将返回nil
答案 2 :(得分:1)
更改代码时,应解决以下问题。
# ...
game2.each{ |server, data|
if server == 'server3'
puts data['url']
end
}
# ...
您遇到类型错误,因为产生的值server
是一个数组,而不是一个哈希。这种情况正在发生,因为您在game2
变量上调用每个变量,这是一个哈希值,并且仅产生一个变量。
hash = { one: 1, two: 2, three: 3 }
当Hash#each仅使用一个变量调用时,当前键和值将按照[key, value]
hash.each do |number|
puts number.inspect
end
# Prints
# [:one, 1]
# [:two, 2]
# [:three, 3]
当Hash#each用两个变量调用时,当前键将被分配给第一个变量,当前值将被分配给第二个变量。
hash.each do |key, value|
puts "Key: #{key}; Value: #{value}"
end
# Prints:
# Key: one; Value: 1
# Key: two; Value: 2
# Key: three; Value: 3