¿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

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"]}]}

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


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"}}}}}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.