Ruby-on-rails 将 YAML 与变量一起使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4150782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:37:07  来源:igfitidea点击:

Use YAML with variables

ruby-on-railsrubyvariablesyamlstring-interpolation

提问by brewster

Are variables within YAML files possible? For example:

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

theme:
  name: default
  css_path: compiled/themes/$theme.name
  layout_path: themes/$theme.name

In this example, how can theme: name: defaultbe used in other settings? What is the syntax?

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

回答by benrugg

I had this same question, and after a lot of research, it looks like it's not possible.

我有同样的问题,经过大量研究,似乎不可能

The answer from cgat is on the right track, but you can't actually concatenate references like that.

cgat 的答案是正确的,但您实际上无法连接这样的引用。

Here are things you can do with "variables" in YAML (which are officially called "node anchors" when you set them and "references" when you use them later):

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

Define a value and use an exact copy of it later:

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

default: &default_title This Post Has No Title
title: *default_title

{ or }

{ 或者 }

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.

For more info, see this section of the wiki page about YAML:http://en.wikipedia.org/wiki/YAML#References

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

Define an object and use it with modifications later:

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

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

This is taken directly from a great demo here:https://gist.github.com/bowsersenior/979804

这直接取自这里的一个很棒的演示:https : //gist.github.com/bowsersenior/979804

回答by onionpsy

After some search, I've found a cleaner solution wich use the %operator.

经过一番搜索,我找到了一个使用%运算符的更清洁的解决方案。

In your YAML file :

在您的 YAML 文件中:

key : 'This is the foobar var : %{foobar}'

In your ruby code :

在你的红宝石代码中:

require 'yaml'

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

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

puts modified_content

And the output is :

输出是:

This is the foobar var : Hello World !


As @jschorr said in the comment, you can also add multiple variable to the value in the Yaml file :

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

Yaml :

亚姆:

key : 'The foo var is %{foo} and the bar var is %{bar} !'

Ruby :

红宝石:

# ...
foo = 'FOO'
bar = 'BAR'
# ...
modified_content = content % { :foo => foo, :bar => bar }

Output :

输出 :

The foo var is FOO and the bar var is BAR !

回答by Ben

This is an old post, but I had a similar need and this is the solution I came up with. It is a bit of a hack, but it works and could be refined.

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

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

A big downside is that it builds into the yaml document a variable name (in this case, "data") that may or may not exist. Perhaps a better solution would be to use $ and then substitute it with the variable name in Ruby prior to ERB. Also, just tested using hashes2ostructwhich allows data.theme.name type notation which is much easier on the eyes. All that is required is to wrap the YAML::load with this

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

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

Then your YAML document can look like this

那么你的 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

回答by Mirv - Matt

Rails / ruby frameworks are able to do some templating ... it's frequently used to load env variables ...

Rails / ruby​​ 框架能够做一些模板......它经常用于加载 env 变量......

# fooz.yml
  foo:
    bar: <%= $ENV[:some_var] %>

No idea if this works for javascript frameworks as I think that YML format is superset of json and it depends on what reads the yml file for you.

不知道这是否适用于 javascript 框架,因为我认为 YML 格式是 json 的超集,这取决于为您读取 yml 文件的内容。

If you can use the template like that or the << >>or the {{ }}styles depending on your reader, after that you just ...

如果您可以根据您的读者使用这样的模板<< >>{{ }}样式,那么之后您只需...

In another yml file ...

在另一个 yml 文件中...

# boo.yml

development:
  fooz: foo

Which allows you to basically insert a variable as your reference that original file each time which is dynamically set. When reading I was also seeing you can create or open YML files as objects on the fly for several languages which allows you to create a file & chain write a series of YML files or just have them all statically pointing to the dynamically created one.

这允许您基本上插入一个变量作为您每次动态设置的原始文件的参考。在阅读时,我还看到您可以为多种语言动态创建或打开 YML 文件作为对象,这允许您创建文件并链式写入一系列 YML 文件,或者让它们全部静态指向动态创建的文件。