<<
エイリアス化されたマッピングを現在のマッピングにマージする必要があることを示すために を使用することは、コア Yaml 仕様の一部ではありませんが、タグ リポジトリの一部です。
Ruby が提供する現在の Yaml ライブラリ – Psych – は、Ruby オブジェクトの簡単なシリアル化と逆シリアル化を可能にし、ハッシュのマージを含むタグ リポジトリでさまざまな暗黙的な型変換を使用できるメソッドdump
とメソッドを提供します。また、必要に応じて、より低レベルの Yaml 処理を行うためのツールも提供します。残念ながら、タグ リポジトリの特定の部分を選択的に無効または有効にすることは容易ではありません。これは、全か無かの問題です。特に、の処理は hash の処理にかなり組み込まれています。load
<<
<<
目的を達成する 1 つの方法は、Psych のToRuby
クラスの独自のサブクラスを提供し、このメソッドをオーバーライドして、のマッピング キーを<<
リテラルとして扱うだけにすることです。これには、Psych でプライベート メソッドをオーバーライドする必要があるため、少し注意する必要があります。
require 'psych'
class ToRubyNoMerge < Psych::Visitors::ToRuby
def revive_hash hash, o
@st[o.anchor] = hash if o.anchor
o.children.each_slice(2) { |k,v|
key = accept(k)
hash[key] = accept(v)
}
hash
end
end
次に、次のように使用します。
tree = Psych.parse your_data
data = ToRubyNoMerge.new.accept tree
あなたの例のYamlを使用すると、次のdata
ようになります
{"defaults"=>{"foo"=>"bar", "zip"=>"button"},
"node"=>{"<<"=>{"foo"=>"bar", "zip"=>"button"}, "foo"=>"other"}}
<<
リテラルキーとして注意してください。また、キーの下のハッシュは、data["defaults"]
キーの下のハッシュと同じdata["node"]["<<"]
です。つまり、同じobject_id
. 必要に応じてデータを操作できるようになりました。Yaml として書き出すと、アンカー名は変更されますが、アンカーとエイリアスはそのまま残ります。
data['node']['foo'] = "yet another"
puts Yaml.dump data
(Psych はobject_id
ハッシュの を使用して一意のアンカー名を確保します (現在のバージョンの Psych では ではなく連番を使用していますobject_id
)):
---
defaults: &2151922820
foo: bar
zip: button
node:
<<: *2151922820
foo: yet another
アンカー名を制御したい場合は、独自のPsych::Visitors::Emitter
. これは、あなたの例に基づいた簡単な例であり、アンカーが1つしかないと仮定しています:
class MyEmitter < Psych::Visitors::Emitter
def visit_Psych_Nodes_Mapping o
o.anchor = 'defaults' if o.anchor
super
end
def visit_Psych_Nodes_Alias o
o.anchor = 'defaults' if o.anchor
super
end
end
上記の変更されたdata
ハッシュで使用すると、次のようになります。
#create an AST based on the Ruby data structure
builder = Psych::Visitors::YAMLTree.new
builder << data
ast = builder.tree
# write out the tree using the custom emitter
MyEmitter.new($stdout).accept ast
出力は次のとおりです。
---
defaults: &defaults
foo: bar
zip: button
node:
<<: *defaults
foo: yet another
(更新: 別の質問で、複数のアンカーでこれを行う方法が尋ねられました。シリアル化するときにアンカー名を保持するためのおそらくより良い方法を思いつきました。)