Use YAML con variables

¿Son posibles las variables dentro de los archivos YAML? Por ejemplo:

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

En este ejemplo, ¿cómo se puede usar theme: name: default en otras configuraciones? ¿Cuál es la syntax?

Tenía la misma pregunta, y después de mucha investigación, parece que no es posible .

La respuesta de cgat está en el camino correcto, pero en realidad no se pueden concatenar referencias como esa.

Aquí hay cosas que puede hacer con las “variables” en YAML (que oficialmente se denominan “anclajes de nodo” cuando las establece y “referencias” cuando las usa más adelante):

Defina un valor y use una copia exacta de él más tarde:

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

{o}

 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. 

Para obtener más información, consulte esta sección de la página wiki sobre YAML: http://en.wikipedia.org/wiki/YAML#References

Defina un objeto y utilícelo con modificaciones posteriores:

 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 

Esto se toma directamente de una gran demostración aquí: https://gist.github.com/bowsersenior/979804

Después de buscar, encontré una solución más limpia que usa el operador % .

En tu archivo YAML:

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

En tu código Ruby:

 require 'yaml' file = YAML.load_file('your_file.yml') foobar = 'Hello World !' content = file['key'] modified_content = content % { :foobar => foobar } puts modified_content 

Y la salida es:

 This is the foobar var : Hello World ! 

Como dijo @jschorr en el comentario, también puedes agregar múltiples variables al valor en el archivo 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 } 

Salida:

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

Esta es una publicación anterior, pero tenía una necesidad similar y esta es la solución que se me ocurrió. Es un truco, pero funciona y podría ser refinado.

 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 

Un gran inconveniente es que incorpora en el documento yaml un nombre de variable (en este caso, “datos”) que puede existir o no. Quizás una mejor solución sería usar $ y luego sustituirlo por el nombre de la variable en Ruby antes de ERB. Además, acaba de probar usando hashes2ostruct que permite la notación tipo data.theme.name que es mucho más fácil para los ojos. Todo lo que se requiere es envolver la carga YAML :: con este

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

Entonces su documento YAML puede verse así

 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