将YAML与变量一起使用

bre*_*ter 75 ruby variables yaml ruby-on-rails string-interpolation

YAML文件中的变量是否可能?例如:

theme:
  name: default
  css_path: compiled/themes/$theme.name
  layout_path: themes/$theme.name
Run Code Online (Sandbox Code Playgroud)

在这个例子中,如何theme: name: default在其他设置中使用?语法是什么?

ben*_*ugg 100

我有同样的问题,经过大量的研究,看起来不可能.

cgat的答案是在正确的轨道上,但你实际上不能连接这样的引用.

以下是您可以使用YAML中的"变量"执行的操作(在设置它们时可以正式称为"节点锚点",以后使用时可以使用"引用"):

定义一个值并稍后使用它的精确副本:

default: &default_title This Post Has No Title
title: *default_title
Run Code Online (Sandbox Code Playgroud)

{ 要么 }

example_post: &example
  title: My mom likes roosters
  body: Seriously, she does. And I don't know when it started.
  date: 8/18/2012
first_post: *example
second_post:
  title: whatever, etc.
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅有关YAML的Wiki页面的此部分: http ://en.wikipedia.org/wiki/YAML#References

定义一个对象并在以后修改时使用它:

default: &DEFAULT
  URL:          stooges.com
  throw_pies?:  true  
  stooges:  &stooge_list
    larry:  first_stooge
    moe:    second_stooge
    curly:  third_stooge

development:
  <<: *DEFAULT
  URL:      stooges.local
  stooges: 
    shemp: fourth_stooge

test:
  <<: *DEFAULT
  URL:    test.stooges.qa
  stooges: 
    <<: *stooge_list
    shemp: fourth_stooge
Run Code Online (Sandbox Code Playgroud)

这可以直接从一个很棒的演示中获取: https ://gist.github.com/bowsersenior/979804

  • `&lt;&lt;` 有什么作用?我似乎无法在[文档](http://docs.ansible.com/ansible/YAMLSyntax.html)中找到它。 (2认同)

oni*_*psy 43

经过一番搜索,我找到了一个使用%操作员的清洁解决方案.

在您的YAML文件中:

key : 'This is the foobar var : %{foobar}'
Run Code Online (Sandbox Code Playgroud)

在您的ruby代码中:

require 'yaml'

file = YAML.load_file('your_file.yml')

foobar = 'Hello World !'
content = file['key']
modified_content = content % { :foobar => foobar }

puts modified_content
Run Code Online (Sandbox Code Playgroud)

输出是:

This is the foobar var : Hello World !
Run Code Online (Sandbox Code Playgroud)

正如@jschorr在评论中所说,您还可以将多个变量添加到Yaml文件中的值:

Yaml:

key : 'The foo var is %{foo} and the bar var is %{bar} !'
Run Code Online (Sandbox Code Playgroud)

Ruby:

# ...
foo = 'FOO'
bar = 'BAR'
# ...
modified_content = content % { :foo => foo, :bar => bar }
Run Code Online (Sandbox Code Playgroud)

输出:

The foo var is FOO and the bar var is BAR !
Run Code Online (Sandbox Code Playgroud)

  • 阅读有关 Ruby 字符串的 `%` 运算符的更多信息:http://ruby-doc.org/core-2.2.3/String.html#method-i-25 (2认同)

小智 4

这是一篇旧帖子,但我有类似的需求,这是我想出的解决方案。这有点像黑客,但它有效并且可以改进。

require 'erb'
require 'yaml'

doc = <<-EOF
  theme:
  name: default
  css_path: compiled/themes/<%= data['theme']['name'] %>
  layout_path: themes/<%= data['theme']['name'] %>
  image_path: <%= data['theme']['css_path'] %>/images
  recursive_path: <%= data['theme']['image_path'] %>/plus/one/more
EOF

data = YAML::load("---" + doc)

template = ERB.new(data.to_yaml);
str = template.result(binding)
while /<%=.*%>/.match(str) != nil
  str = ERB.new(str).result(binding)
end

puts str
Run Code Online (Sandbox Code Playgroud)

一个很大的缺点是它在 yaml 文档中构建了一个可能存在也可能不存在的变量名称(在本例中为“数据”)。也许更好的解决方案是使用 $,然后在 ERB 之前将其替换为 Ruby 中的变量名称。另外,刚刚使用hashes2ostruct进行了测试,它允许 data.theme.name 类型表示法,这对眼睛来说更容易。所需要做的就是用这个包装 YAML::load

data = hashes2ostruct(YAML::load("---" + doc))
Run Code Online (Sandbox Code Playgroud)

那么你的 YAML 文档可以是这样的

doc = <<-EOF
  theme:
  name: default
  css_path: compiled/themes/<%= data.theme.name %>
  layout_path: themes/<%= data.theme.name %>
  image_path: <%= data.theme.css_path %>/images
  recursive_path: <%= data.theme.image_path %>/plus/one/more
EOF
Run Code Online (Sandbox Code Playgroud)