💎

YPS: YAML Positioning Systemご紹介

に公開

YPS: YAML Positioning Systemご紹介

初めに

YAMLはRuby界隈では広く使われている構造化テキストのフォーマットです。Rubyに同梱されているYAMLを使えば、簡単にYAML文字列をRubyオブジェクトに変換することが出来ます。

yaml = <<~'YAML'
  - Taro san
  - Jiro san
  - Saburo san
YAML
YAML.load(yaml) # => ["Taro san", "Jiro san", "Saburo san"]

しかし、変換後のオブジェクトには、変換元のYAML上の位置情報が保持されていません。
変換後の値に不備があって、入力のYAMLが大きいと、そのデバッグ(目grep)は困難です。

そこで、位置情報付きのオブジェクトに変換するGem、YPS: YAML Positioning Systemを作成しました。

使い方

YPSにはYAMLをパースするメソッドとして、以下の4つのメソッドが定義されています。

  • YPS.safe_load
    • Psych.safe_load相当のメソッドで、入力されたYAML文字列をRubyオブジェクトに変換します。
  • YPS.load
    • YPS.safe_loadとほとんど同じですが、デフォルトでSymbolの読み込みが許可されていまs。
  • YPS.safe_load_file
    • YPS.safe_loadのファイル入力版です。
  • YPS.load_file
    • YPS.loadのファイル入力版です。

これらのメソッドを使ってYAMLから変換したRubyオブジェクト(Hashのキーは除く)には、変換元のYAML上の位置情報がを返す#positionメソッドが定義されています。このメソッドを使うことで、変換元のYAML上の位置情報を取得することが出来ます。

require 'yps'

yaml = YPS.load(<<~'YAML')
children:
  - name: kanta
    age: 8
  - name: kaede
    age: 3
YAML

# output
# name: kanta (filename: unknown line 2 column 11)
# age: 8 (filename: unknown line 3 column 10)
# name: kaede (filename: unknown line 4 column 11)
# age: 3 (filename: unknown line 5 column 10)
yaml['children'].each do |child|
  child.each do |key, value|
    puts "#{key}: #{value} (#{value.position})"
  end
end

Discussion