feat(visitor): allow to create custom object (instead of Hash) according to context#299
Open
kwatch wants to merge 8 commits intoruby:masterfrom
Open
feat(visitor): allow to create custom object (instead of Hash) according to context#299kwatch wants to merge 8 commits intoruby:masterfrom
kwatch wants to merge 8 commits intoruby:masterfrom
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.
Member
|
I think I'm OK with the |
Author
|
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. |
Member
|
@kwatch yes, that makes sense. Please do it! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(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.barinstead 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'.