Ruby ハッシュを YAML に変換してコメントを保持するにはどうすればよいですか?

概要

Ruby ハッシュを YAML に変換してコメントを保持するにはどうすればよいですか?

次の Ruby の例の場合

require 'yaml'

h = {
  # The garage in Miami
  'garage_A' => {
    'car_x' => {
      # Bought in Gotham
      'name' => 'Batmobile',
      'color' => 'black'
    }
  },
  'garage_B' => {
    # Mike's bike
    'bike_m' => {
      # Cherry red
      'color' => 'red',
      'wheels' => 2
    }
  }
}

puts YAML.dump(h)

次の結果を取得したいと考えています。

---
# The garage in Miami
garage_A:
  car_x:
    # Bought in Gotham
    name: Batmobile
    color: black
garage_B:
  # Mike's bike
  bike_m:
    # Cherry red
    color: red
    wheels: 2

現在私が得ているものは次のとおりです。

---                                                                                                                                                                                                                  
garage_A:                                                                                                                                                                                                            
  car_x:                                                                                                                                                                                                             
    name: Batmobile                                                                                                                                                                                                  
    color: black                                                                                                                                                                                                     
garage_B:                                                                                                                                                                                                            
  bike_m:                                                                                                                                                                                                            
    color: red                                                                                                                                                                                                       
    wheels: 2  

逆の操作にも興味があるかもしれません。

使用例: ツールのデフォルト設定を含む Ruby ハッシュ。構成ファイルが存在しない場合は、ハッシュを YAML にダンプし、構成ファイルを書き込みます。ユーザーの利便性を考えると、ドキュメントを参照するよりも、設定ファイルにコメントを含めた方がよいでしょう。

解決策

YAML ファイルをヒアドキュメントとしてテンプレート化するか、erb などのテンプレート言語を使用する必要があります。可能であれば、コメントが不要になるように、ハッシュ要素にはより意図が明らかな名前を使用する必要があります。

本当にコメントが必要な場合は、JSON オブジェクトも Ruby Hash オブジェクトも構文の一部としてコメントをネイティブにサポートしていないことに注意してください。その結果、ハッシュ オブジェクトから生成した JSON または YAML 内にそれを表示するには、Ruby ハッシュ内のネストされたオブジェクトごとに「コメント」キー/値のペアを作成する必要があります。例えば:

require "yaml"

# Assign a comment key to each nested element.
hash_with_comments = {
  "comment"  => "nested hashes contain 'comment' keys",
  "garage_a" => {
    "comment" => "The garage in Miami",
    "car_x"   => {
      "comment" => "Bought in Gotham",
      "name"    => "Batmobile",
      "color"   => "black",
    }
  }
}

これで、 hash_with_comments.to_yaml は次の YAML を生成します。

---
comment: nested hashes contain 'comment' keys
garage_a:
  comment: The garage in Miami
  car_x:
    comment: Bought in Gotham
    name: Batmobile
    color: black

ユースケースによっては、そこで停止して、YAML を解析するコード内のコメント キーを無視することもできます。それ以外の場合は、String#gsub ブロック構文 (一致しない行の汚染を避けるためにブロックを使用する必要があります) を使用して、コメント要素を実際のコメントに変換できます。たとえば、次のように呼び出します。

hash_with_comments.to_yaml.gsub(/^(\s*)comment:/) { "#{$1}#" }

コメント キーを実際のコメントに変換すると、次の YAML が生成されます。

---
# each Hash contains a 'comment' key
garage_a:
  # The garage in Miami
  car_x:
    # Bought in Gotham
    name: Batmobile
    color: black