-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(visitor): allow to create custom object (instead of Hash) according to context #299
base: master
Are you sure you want to change the base?
Conversation
This is necessary to create custom object as mapping instead of Hash. For example, if you prefer `hashobj.key` instead of `hashobj['key']`: ## allows `h.foo` instead of `h['foo']` class MagicHash < Hash def method_missing(method, *args) return super unless args.empty? return self[method.to_s] end end ## override to generate MagicHash instead of Hash class MagicVisitor < Psych::Visitors::ToRuby def empty_mapping(o) MagicHash.new end end ## example to access `ydoc.foo` instead of `ydoc['foo']` input = <<'END' tables: - name: admin_users columns: - name: id type: int pkey: true END tree = Psych.parse(input) visitor = MagicVisitor.create ydoc = visitor.accept(tree) p ydoc.tables[0].columns[0].name #=> "name" p ydoc.tables[0].columns[0].type #=> "int"
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
This new class allows user to generate custom object instead of Hash. See document of CustomClassVisitor class for details.
I think I'm OK with the |
Thanks a lot.
I see. I'll revert the following commits.
And I'll leave the rest commits.
Is it OK? Give me your advice. |
@kwatch yes, that makes sense. Please do it! |
(Redirected from https://bugs.ruby-lang.org/issues/12960?next_issue_id=12959 .)
New visitor class to create custom object intead of Hash.
It creates custom object according to context (= last mapping key).
ydoc.foo.bar
instead ofydoc['foo']['bar']
.ydoc['teams'][0].is_a?(Team)
andydoc['teams'][0].members[0].is_a?(Member)
.See document of CustomClassVisitor class for details.
You may feel that CustomClassVisitor is very experimental. I hope that at least changes of 'to_ruby.rb' will be imported to upstream, because implementation of CustomClassVisitor requires monkey-pathing to 'to_ruby.rb'.