【问题标题】:Ruby yaml custom domain type does not keep classRuby yaml 自定义域类型不保留类
【发布时间】:2012-06-28 07:24:50
【问题描述】:

我正在尝试将持续时间对象(来自 ruby-duration gem)转储到具有自定义类型的 yaml,因此它们以 hh:mm:ss 的形式表示。我试图从this question 修改答案,但是当使用 YAML.load 解析 yaml 时,返回的是 Fixnum 而不是 Duration。有趣的是,Fixnum 是持续时间的总秒数,因此解析似乎有效,但之后转换为 Fixnum。

到目前为止我的代码:

class Duration
  def to_yaml_type
    "!example.com,2012-06-28/duration"
  end

  def to_yaml(opts = {})
    YAML.quick_emit( nil, opts ) { |out|
      out.scalar( to_yaml_type, to_string_representation, :plain )
    }
  end

  def to_string_representation
    format("%h:%m:%s")
  end

  def Duration.from_string_representation(string_representation)
    split = string_representation.split(":")
    Duration.new(:hours => split[0], :minutes => split[1], :seconds => split[2])
  end
end

YAML::add_domain_type("example.com,2012-06-28", "duration") do |type, val|
  Duration.from_string_representation(val)
end

澄清一下,我得到了什么结果:

irb> Duration.new(27500).to_yaml
=> "--- !example.com,2012-06-28/duration 7:38:20\n...\n"
irb> YAML.load(Duration.new(27500).to_yaml)
=> 27500
# should be <Duration:0xxxxxxx @seconds=20, @total=27500, @weeks=0, @days=0, @hours=7, @minutes=38>

【问题讨论】:

    标签: ruby yaml


    【解决方案1】:

    看起来您使用的是旧版 Syck 界面,而不是新版 Psych。您可以使用encode_with,而不是使用to_yamlYAML.quick_emit,而不是add_domain_type,使用add_taginit_with。 (这方面的文档很差,我能提供的最好的是link to the source)。

    class Duration
      def to_yaml_type
        "tag:example.com,2012-06-28/duration"
      end
    
      def encode_with coder
        coder.represent_scalar to_yaml_type, to_string_representation
      end
    
      def init_with coder
        split = coder.scalar.split ":"
        initialize(:hours => split[0], :minutes => split[1], :seconds => split[2])
      end
    
      def to_string_representation
        format("%h:%m:%s")
      end
    
      def Duration.from_string_representation(string_representation)
        split = string_representation.split(":")
        Duration.new(:hours => split[0], :minutes => split[1], :seconds => split[2])
      end
    end
    
    YAML.add_tag "tag:example.com,2012-06-28/duration", Duration
    
    p s = YAML.dump(Duration.new(27500))
    p YAML.load s
    

    这个输出是:

    "--- !<tag:example.com,2012-06-28/duration> 7:38:20\n...\n"
    #<Duration:0x00000100e0e0d8 @seconds=20, @total=27500, @weeks=0, @days=0, @hours=7, @minutes=38>
    

    (您看到的结果是 Duration 中的总秒数,因为它被解析为 sexagesimal integer。)

    【讨论】:

    • 完美运行,感谢您的解释,为什么我得到了秒。一旦我被允许,我会奖励你的赏金
    猜你喜欢
    • 2014-03-23
    • 2020-01-17
    • 1970-01-01
    • 2015-07-12
    • 2020-11-11
    • 2018-12-20
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    相关资源
    最近更新 更多