¿Cómo analizo un archivo YAML en Ruby?

210

Me gustaría saber cómo analizar un archivo YAML con los siguientes contenidos:

--- 
javascripts: 
- fo_global:
  - lazyload-min
  - holla-min

Actualmente estoy tratando de analizarlo de esta manera:

@custom_asset_packages_yml = (File.exists?("#{RAILS_ROOT}/config/asset_packages.yml") ? YAML.load_file("#{RAILS_ROOT}/config/asset_packages.yml") : nil)
    if !@custom_asset_packages_yml.nil?
      @custom_asset_packages_yml['javascripts'].each{ |js|
        js['fo_global'].each{ |script|
         script
        }
      }
    end

Pero no parece funcionar y me da un error de que el valor es nulo.

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Si intento esto, saca la cadena completa (fo_globallazyload-minholla-min):

if !@custom_asset_packages_yml.nil?
          @custom_asset_packages_yml['javascripts'].each{ |js|
            js['fo_global']
          }
        end
alvincrespo
fuente
1
¿Puedes dar el resultado del script cuando lo ejecutas? archivos en el lugar correcto? siempre puedes encender una consola Rails y ver si Ruby también puede ver ese camino.
Lukas
Sí, el archivo existe y está en la ubicación correcta. He actualizado mi publicación con el error.
alvincrespo

Respuestas:

449

Tal vez me falta algo, pero ¿por qué intentar analizar el archivo? ¿Por qué no simplemente cargar el YAML y examinar los objetos que resultan?

Si su muestra YAML está dentro some.yml, entonces esto:

require 'yaml'
thing = YAML.load_file('some.yml')
puts thing.inspect

me da

{"javascripts"=>[{"fo_global"=>["lazyload-min", "holla-min"]}]}
Mike Woodhouse
fuente
9
Estoy de acuerdo, eso es lo maravilloso de YAML: podemos serializar algo y luego volver a leerlo, así que ¿por qué no usar esa capacidad?
El hombre de hojalata
Ah, no sabía que podías hacer eso con un archivo YAML. ¡Muchas gracias!
alvincrespo
1
Eh, fue porque estaba usando pestañas. Parece que solo quiere espacios en lugar de pestañas, y luego arroja todo tipo de errores.
FilBot3
3
¿Cuál es la diferencia entre #load y #load_file en la biblioteca YAML?
Jwan622
3
YAML.loadtoma una cadena YAML, YAML.load_filetoma una ruta de archivo relativa.
Narfanator
11

Tuve el mismo problema pero también quería obtener el contenido del archivo (después de la presentación de YAML).

Esta es la mejor solución que he encontrado:

if (md = contents.match(/^(?<metadata>---\s*\n.*?\n?)^(---\s*$\n?)/m))
  self.contents = md.post_match
  self.metadata = YAML.load(md[:metadata])
end

Fuente y discusión: https://practicingruby.com/articles/tricks-for-working-with-text-and-files

sarfata
fuente
1
Link ahora parece estar practicando
ruby.com/articles/…
Gracias @devstuff - He actualizado el enlace en la respuesta.
sarfata
3

Aquí está el único trazador de líneas que uso, desde la terminal, para probar el contenido de los archivos yml:

$ ruby  -r yaml -r pp  -e 'pp YAML.load_file("/Users/za/project/application.yml")'
{"logging"=>
  {"path"=>"/var/logs/",
   "file"=>"TacoCloud.log",
   "level"=>
    {"root"=>"WARN", "org"=>{"springframework"=>{"security"=>"DEBUG"}}}}}
zee
fuente