Use YAML with variables

前端 未结 5 983
你的背包
你的背包 2020-11-28 22:47

Are variables within YAML files possible? For example:

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


        
相关标签:
5条回答
  • 2020-11-28 23:04

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

    In your YAML file :

    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 :

    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 !
    
    0 讨论(0)
  • 2020-11-28 23:14

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

    # 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.

    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 ...

    # 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.

    0 讨论(0)
  • 2020-11-28 23:20

    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.

    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):

    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

    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

    0 讨论(0)
  • 2020-11-28 23:21

    if your requirement is like parsing an replacing multiple variable and then use it as a hash/or anything then you can do something like this

    require 'yaml'
    require 'json'
    yaml = YAML.load_file("xxxx.yaml")
    blueprint = yaml.to_json % { var_a: "xxxx", var_b: "xxxx"}
    hash = JSON.parse(blueprint)
    

    inside the yaml just put variables like this

    "%{var_a}"
    
    0 讨论(0)
  • 2020-11-28 23:29

    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 hashes2ostruct which 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

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

    Then your YAML document can look like this

    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
    
    0 讨论(0)
提交回复
热议问题