-
Notifications
You must be signed in to change notification settings - Fork 209
feat(visitor): allow to create custom object (instead of Hash) according to context #299
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
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.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'.