Bagaimana cara mem-parsing file YAML di Ruby?


210

Saya ingin tahu cara mem-parsing file YAML dengan konten berikut:

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

Saat ini saya mencoba menguraikannya dengan cara ini:

@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

Tapi sepertinya tidak berfungsi dan memberi saya kesalahan bahwa nilainya nol.

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

Jika saya mencoba ini, ia mengeluarkan seluruh string (fo_globallazyload-minholla-min):

if !@custom_asset_packages_yml.nil?
          @custom_asset_packages_yml['javascripts'].each{ |js|
            js['fo_global']
          }
        end

1
dapatkah Anda memberikan output dari skrip saat Anda menjalankannya? file di tempat yang tepat? Anda selalu dapat menjalankan konsol Rails dan melihat apakah ruby ​​dapat melihat jalur itu juga.
— Lukas

Ya, file itu ada dan berada di lokasi yang tepat. Saya sudah memperbarui posting saya dengan kesalahan.
— alvincrespo

Jawaban:


449

Mungkin saya melewatkan sesuatu, tetapi mengapa mencoba mengurai file? Mengapa tidak hanya memuat YAML dan memeriksa objek yang dihasilkannya?

Jika sampel Anda YAML ada some.yml, maka ini:

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

memberi saya

{"javascripts"=>[{"fo_global"=>["lazyload-min", "holla-min"]}]}

9
Saya setuju, itu bagus tentang YAML - kita bisa membuat serial sesuatu lalu membacanya kembali nanti, jadi mengapa tidak menggunakan kemampuan itu.
— the Tin Man

Ah, saya tidak menyadari bahwa Anda dapat melakukannya dengan file YAML. Terima kasih banyak!
— alvincrespo

1
Huh, itu karena saya menggunakan tab. Tampaknya hanya menginginkan spasi alih-alih tab, dan kemudian melempar semua jenis kesalahan.
— FilBot3

3
Apa perbedaan antara #load dan #load_file di pustaka YAML?
— Jwan622

3
YAML.loadmengambil string YAML, YAML.load_filemengambil jalur file relatif.
— Narfanator

11

Saya memiliki masalah yang sama tetapi juga ingin mendapatkan konten dari file tersebut (setelah materi utama YAML).

Ini adalah solusi terbaik yang saya temukan:

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

Sumber dan diskusi: https://practicingruby.com/articles/tricks-for-working-with-text-and-files


1
Tautan sekarang tampaknya sedang berlatihruby.com/articles/…
— devstuff

Terima kasih @ evstuff - Saya telah memperbarui tautan dalam jawabannya.
— sarfata

3

Ini adalah satu liner yang saya gunakan, dari terminal, untuk menguji konten file 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"}}}}}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.