我正在尝试使用自定义类型将持续时间对象(从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>
答案 0 :(得分:6)
看起来你正在使用较旧的Syck界面,而不是较新的Psych。您可以使用to_yaml
,而不是YAML.quick_emit
使用encode_with
和add_domain_type
,而不是使用add_tag
和init_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>
(您看到的结果是持续时间中的总秒数,因为它被解析为sexagesimal integer。)