心理医生说:“在中级阶段正在建立AST…",但是,究竟如何呢? [英] Psych doc says «At the mid level is building an AST…» but, how exactly?
问题描述
我使用Sych
做这个旧代码:
yaml_as "tag:yaml.org,2002:#{self}"
def to_yaml(opts = {})
YAML::quick_emit(self, opts) do |out|
out.map(taguri, to_yaml_style) do |map|
map.add('name', name)
map.add('address', full_address.upcase) if full_address?
end
end
end
输出类似这样的内容:
--- !Contact
name: SMOKE OIL
address: |-
SMOKE OIL
1 RUE DE LA PAIX
75002 PARIS
FRANCE
现在,我正在升级旧代码,转到Psych
,因此,我阅读了文档并做了:
Now, I'm upgrading that old code, going to Psych
so, I read the doc and did :
yaml_as "tag:yaml.org,2002:#{self}"
def encode_with(coder)
coder['name'] = name
coder['address'] = full_address.upcase if full_address?
end
而且可以:
--- !Contact
name: SMOKE OIL
address: ! "SMOKE OIL\n1 RUE DE LA PAIX\n75002 PARIS\nFRANCE"
这是一个不错的YAML,但是,它应该是whois服务器的输出,而且人类对它的可读性也较低……
It's nice YAML but, it's supposed to be the output of a whois server, and it's way less readable by humans…
因此,我回到文档上来,研究了第二种处理方式,即构建AST.现在,除非我没看到任何东西,否则没有任何东西可以向您说明如何使用您构建的AST,并以Psych.dump(obj)仍能正常工作的方式将其插入…
So, I went back to the doc, and looked at the second way of doing things, that is, building an AST. Now, unless I'm not seeing something, nothing explains you how to take the AST you built, and plug it in a way Psych.dump(obj) would still work…
我尝试做(没有太大希望):
I tried doing (without much hope) :
a = Psych::Nodes::Scalar(full_address.upcase)
a.style = Psych::Nodes::LITTERAL
coder['address'] = a if full_address?
但是,显然,它没有实现我希望的那样……我也尝试过:
but, obviously, it did not do what I hoped it'd do… I also tried :
def encode_with(coder)
Psych::Nodes::Mapping.new.tap do |map|
map.children << Psych::Nodes::Scalar.new("name")
map.children << Psych::Nodes::Scalar.new(name)
map.children << Psych::Nodes::Scalar.new("address")
a = Psych::Nodes::Scalar.new(full_address.upcase)
a.style = 4
map.children << a
end
end
但是,我看不到如何将其插入编码器中……
But, I could not see how to plug it into the coder…
此外,做递归操作时答案需要起作用,这是一个Contact
对象,但是人们可以要求一个包含几个联系人的Domain
,我希望它尽可能地干:-)
Also, the answer needs to work when doing recursive things, this is a Contact
objet, but one can ask for a Domain
which will contain a few contacts and I want it as DRY as possible :-)
那么,任何人都有关于如何执行此操作的提示吗?
So, anyone has a hint on how to do this ?
推荐答案
如果要创建自己的AST,则不能使用Psych.dump
. Psych.dump
使用Psych默认值创建自己的AST.在您的情况下,您想自定义AST创建过程.
If you want to create your own AST then you can’t use Psych.dump
. Psych.dump
creates its own AST using the Psych defaults. In your case you want to customise the AST creation process.
查看Psych.dump
的来源您会看到它使用了 Psych::Visitors::YAMLTree
创建AST.您可以将此子类化,并自定义其处理Contact
类的方式以获取所需的输出.特别是,您需要覆盖
Looking at the source of Psych.dump
you can see it uses a Psych::Visitors::YAMLTree
to create the AST. You can subclass this and customise how it handles your Contact
class to get the output you want. In particular you need to override the accept
method.
这是一个简单的示例,其中只是Contact
类的特殊情况:
Here’s a simple example that just special cases the Contact
class:
class MyYAMLTree < Psych::Visitors::YAMLTree
def accept target
return super unless target.is_a? Contact
@emitter.start_mapping(nil, "tag:yaml.org,2002:#{target.class}", false, Psych::Nodes::Mapping::BLOCK)
@emitter.scalar 'name', nil, nil, true, false, Psych::Nodes::Scalar::ANY
@emitter.scalar target.name, nil, nil, true, false, Psych::Nodes::Scalar::ANY
@emitter.scalar 'address', nil, nil, true, false, Psych::Nodes::Scalar::ANY
#this is the where we make the address string a literal
@emitter.scalar target.full_address, nil, nil, true, false, Psych::Nodes::Scalar::LITERAL
@emitter.end_mapping
end
end
请注意,调用encode_with
的是Psych::Visitors::YAMLTree
类,这将在您的课程中完全绕开它.
Note that it’s the Psych::Visitors::YAMLTree
class that calls encode_with
, this will bypass it altogether for your class.
要使用此功能,请使用类似的东西(这基本上是使用MyYAMLTree的Psych.dump
的简化版本):
In order to use this, use something like (this is basically a simplified version of Psych.dump
using MyYAMLTree):
def my_yaml o
visitor = MyYAMLTree.new
visitor << o
visitor.tree.yaml
end
这显然只是一个简单的示例,但希望它将为您指明正确的方向.
This is obviously just a simple example, but hopefully it’ll point you in the right direction.
这篇关于心理医生说:“在中级阶段正在建立AST…",但是,究竟如何呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!