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
alvincrespo
sumber
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"]}]}
Mike Woodhouse
sumber
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

sarfata
sumber
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"}}}}}
zee
sumber