Ruby 心理医生说«;中层正在建设一个AST&x2026»;但是,具体如何?

Ruby 心理医生说«;中层正在建设一个AST&x2026»;但是,具体如何?,ruby,string,yaml,psych,Ruby,String,Yaml,Psych,我使用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?

我使用
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
所以,我阅读了文档并做了:

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服务器的输出,而且它的可读性要差得多

因此,我回到了博士那里,研究了第二种方法,即构建AST。现在,除非我没有看到什么东西,否则没有任何东西可以解释如何使用您构建的AST,并以Psych.dump(obj)仍然可以工作的方式插入它

我试着做(没有多大希望):

但是,很明显,它没有达到我希望的效果……我也尝试过:

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
def encode_与(编码器)
Psych::Nodes::Mapping.new.tap do | map|

map.children如果要创建自己的AST,则不能使用
Psych.dump
Psych.dump
使用Psych默认值创建自己的AST。在您的情况下,您希望自定义AST创建过程

查看,您可以看到它使用创建AST。您可以将其子类化,并自定义它如何处理您的
Contact
类,以获得所需的输出。特别是,您需要覆盖

下面是一个简单的示例,仅用于
联系人
类的特殊情况:

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

这显然只是一个简单的例子,但希望它能为您指明正确的方向。

您指的是Syck,而不是Sych,就像原始库一样,对吗?
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
def my_yaml o
  visitor = MyYAMLTree.new
  visitor << o
  visitor.tree.yaml
end