From: nobu@... Date: 2016-11-19T04:02:08+00:00 Subject: [ruby-core:78214] [Ruby trunk Feature#12960][Third Party's Issue] [psych] new visitor class to generate custom object instead of Hash Issue #12960 has been updated by Nobuyoshi Nakada. Status changed from Open to Third Party's Issue Please send to the [upstream](https://github.com/ruby/psych). ---------------------------------------- Feature #12960: [psych] new visitor class to generate custom object instead of Hash https://bugs.ruby-lang.org/issues/12960#change-61579 * Author: makoto kuwata * Status: Third Party's Issue * Priority: Normal * Assignee: ---------------------------------------- I create a patch to define new useful visitor class for Psych. It generates custom object as mapping data instead of Hash. Normally, you must access YAML document data like `ydoc["foo"]["bar"]["baz"]`. Using this class, you can access data like `ydoc.foo.bar.baz`. Example1: create custom object instead of Hash according to context ~~~ ruby ## define custom classes Team = Struct.new('Team', 'name', 'members') Member = Struct.new('Member', 'name', 'gender') ## create visitor object require 'psych' require 'psych/visitors/custom_class' classmap = { "teams" => Team, "members" => Member, } visitor = Psych::Visitors::CustomClassVisitor.create(classmap) ## example YAML string input = <<-'END' teams: - name: SOS Brigade members: - {name: Haruhi, gender: F} - {name: Kyon, gender: M} - {name: Mikuru, gender: F} - {name: Itsuki, gender: M} - {name: Yuki, gender: F} END ## parse YAML string with creating Team or Member objects according to context tree = Psych.parse(input) ydoc = visitor.accept(tree) p ydoc['teams'][0].class #=> Struct::Team p ydoc['teams'][0]['members'][0].class #=> Struct::Member team = ydoc['teams'][0] p team.name #=> "SOS Brigade" p team.members[0].name #=> "Haruhi" p team.members[0].gender #=> "F" ~~~ Example2: create custom hash object ~~~ ruby ## allows `hash.foo` instead of `hash["foo"]` class MagicHash < Hash def method_missing(method, *args) return super unless args.empty? return self[method.to_s] end end ## create visitor with MagicHash require 'psych' require 'psych/visitors/custom_class' classmap = {'*' => MagicHash} # '*' means default class visitor = Psych::Visitors::CustomClassVisitor.create(classmap) ## example YAML document input = <<-'END' teams: - name: SOS Brigade members: - {name: Haruhi, gender: F} - {name: Kyon, gender: M} - {name: Mikuru, gender: F} - {name: Itsuki, gender: M} - {name: Yuki, gender: F} END ## parse YAML string with creating custom hash object instead of Hash tree = Psych.parse(input) ydoc = visitor.accept(tree) p ydoc.class #=> MagicHash p ydoc['teams'][0].class #=> MagicHash p ydoc['teams'][0]['members'][0].class #=> MagicHash p ydoc.teams[0].members[0].name #=> "Haruhi" p ydoc.teams[0].members[0].gender #=> "F" ~~~ I believe this class is very useful, and hope it to be imported into ruby repository. Let me know your opinion or impression. ---Files-------------------------------- 0002-feat-psych-allow-custom-Hash-object-for-unknown-tagg.patch (781 Bytes) 0001-feat-psych-allow-to-generate-custom-Hash-object.patch (2.04 KB) 0003-feat-psych-add-hook-point-for-mapping-key-and-value.patch (2.35 KB) 0004-feat-psych-add-hook-points-for-mapping-like-object.patch (2.7 KB) 0005-feat-psych-add-hook-points-for-merge.patch (1.53 KB) 0006-feat-psych-refactor-hook-point-methods-for-merge.patch (883 Bytes) 0008-feat-psych-support-key-for-default-custom-class.patch (2.38 KB) 0007-feat-psych-define-Psych-Visitors-CustomClassVisitor-.patch (3.14 KB) 0009-feat-psych-add-test-script.patch (2.7 KB) 0010-feat-psych-add-another-test-case.patch (1.74 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: