From 5c58e9f7116fcb8d0c826b453e093b00a6d76ba1 Mon Sep 17 00:00:00 2001 From: kwatch Date: Sat, 19 Nov 2016 09:01:16 +0900 Subject: [PATCH 3/9] feat(psych): add hook point for mapping key and value This is necessary to generate custom object as mapping instead of Hash according to context. For example: TableObj = Struct.new('TableObj', 'name', 'columns') ColumnObj = Struct.new('ColumnObj', 'name', 'type', 'pkey') class CustomVisitor < Psych::Visitors::ToRuby def initialize(*args) super @key_path = [] # ex: [] -> ['tables'] -> ['tables', 'columns'] end def accept_key(k) # push keys key = super k @key_path << key return key end def accept_value(v) # pop keys value = super v @key_path.pop() return value end def empty_mapping(o) # generate custom object instead of Hash case @key_path.last when 'tables' ; return TableObj.new when 'columns' ; return ColumnObj.new else ; return super o end end end ## example to generate custom object according to context input = <<'END' tables: - name: admin_users columns: - name: id type: int pkey: true END tree = Psych.parse(input) visitor = CustomVisitor.create ydoc = visitor.accept(tree) p ydoc['tables'][0].class #=> Struct::TableObj p ydoc['tables'][0]['columns'][0].class #=> Struct::ColumnObj --- ext/psych/lib/psych/visitors/to_ruby.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb index 5ecb7e7..9eb11bf 100644 --- a/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ext/psych/lib/psych/visitors/to_ruby.rb @@ -336,11 +336,19 @@ def register_empty object list end + def accept_key k + accept(k) + end + + def accept_value v + accept(v) + end + SHOVEL = '<<' def revive_hash hash, o o.children.each_slice(2) { |k,v| - key = accept(k) - val = accept(v) + key = accept_key(k) + val = accept_value(v) if key == SHOVEL && k.tag != "tag:yaml.org,2002:str" case v -- 2.9.3 (Apple Git-75)