YAMLTree builds a YAML ast given a Ruby object. For example:
builder = Psych::Visitors::YAMLTree.new builder << { :foo => 'bar' } builder.tree # => #<Psych::Nodes::Stream .. }
FIXME: Remove the index and count checks in Psych 3.0
# File psych/lib/psych/visitors/yaml_tree.rb, line 47
def self.create options = {}, emitter = nil
emitter ||= TreeBuilder.new
class_loader = ClassLoader.new
ss = ScalarScanner.new class_loader
new(emitter, ss, options)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 54
def self.new emitter = nil, ss = nil, options = nil
return super if emitter && ss && options
if $VERBOSE
warn "This API is deprecated, please pass an emitter, scalar scanner, and options or call #{self}.create() (#{caller.first})"
end
create emitter, ss
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 63
def initialize emitter, ss, options
super()
@started = false
@finished = false
@emitter = emitter
@st = Registrar.new
@ss = ss
@options = options
@coders = []
@dispatch_cache = Hash.new do |h,klass|
method = "visit_#{(klass.name || '').split('::').join('_')}"
method = respond_to?(method) ? method : h[klass.superclass]
raise(TypeError, "Can't dump #{target.class}") unless method
h[klass] = method
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 121
def accept target
# return any aliases we find
if @st.key? target
oid = @st.id_for target
node = @st.node_for target
anchor = oid.to_s
node.anchor = anchor
return @emitter.alias anchor
end
if target.respond_to?(:to_yaml)
begin
loc = target.method(:to_yaml).source_location.first
if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
unless target.respond_to?(:encode_with)
if $VERBOSE
warn "implementing to_yaml is deprecated, please implement \"encode_with\""
end
target.to_yaml(:nodump => true)
end
end
rescue
# public_method or source_location might be overridden,
# and it's OK to skip it since it's only to emit a warning
end
end
if target.respond_to?(:encode_with)
dump_coder target
else
send(@dispatch_cache[target.class], target)
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 90
def finish
@emitter.end_stream.tap do
@finished = true
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 101
def push object
start unless started?
version = []
version = [1,1] if @options[:header]
case @options[:version]
when Array
version = @options[:version]
when String
version = @options[:version].split('.').map { |x| x.to_i }
else
version = [1,1]
end if @options.key? :version
@emitter.start_document version, [], false
accept object
@emitter.end_document !@emitter.streaming?
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 84
def start encoding = Nodes::Stream::UTF8
@emitter.start_stream(encoding).tap do
@started = true
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 96
def tree
finish unless finished?
@emitter.root
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 394
def visit_Array o
if o.class == ::Array
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
o.each { |c| accept c }
@emitter.end_sequence
else
visit_array_subclass o
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 416
def visit_BasicObject o
tag = Psych.dump_tags[o.class]
tag ||= "!ruby/marshalable:#{o.class.name}"
map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
register(o, map)
o.marshal_dump.each(&method(:accept))
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 295
def visit_BigDecimal o
@emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 356
def visit_Class o
raise TypeError, "can't dump anonymous class: #{o}" unless o.name
register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 267
def visit_Complex o
register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
end
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 239
def visit_DateTime o
formatted = if o.offset.zero?
o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
else
o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
end
tag = '!ruby/object:DateTime'
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 164
def visit_Encoding o
tag = "!ruby/encoding"
@emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 197
def visit_Exception o
tag = ['!ruby/exception', o.class.name].join ':'
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
{
'message' => private_iv_get(o, 'mesg'),
'backtrace' => private_iv_get(o, 'backtrace'),
}.each do |k,v|
next unless v
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
accept v
end
dump_ivars o
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 284
def visit_Float o
if o.nan?
@emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
elsif o.infinite?
@emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
nil, nil, true, false, Nodes::Scalar::ANY)
else
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 369
def visit_Hash o
tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}"
implicit = !tag
register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
accept k
accept v
end
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 277
def visit_Integer o
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 351
def visit_Module o
raise TypeError, "can't dump anonymous module: #{o}" unless o.name
register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 216
def visit_NameError o
tag = ['!ruby/exception', o.class.name].join ':'
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
{
'message' => o.message.to_s,
'backtrace' => private_iv_get(o, 'backtrace'),
}.each do |k,v|
next unless v
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
accept v
end
dump_ivars o
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 404
def visit_NilClass o
@emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 169
def visit_Object o
tag = Psych.dump_tags[o.class]
unless tag
klass = o.class == Object ? nil : o.class.name
tag = ['!ruby/object', klass].compact.join(':')
end
map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
register(o, map)
dump_ivars o
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 156
def visit_Psych_Omap o
seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK)
register(o, seq)
o.each { |k,v| visit_Hash k => v }
@emitter.end_sequence
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 383
def visit_Psych_Set o
register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
accept k
accept v
end
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 361
def visit_Range o
register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
accept m
end
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 254
def visit_Rational o
register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
[
'denominator', o.denominator.to_s,
'numerator', o.numerator.to_s
].each do |m|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
end
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 235
def visit_Regexp o
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 299
def visit_String o
plain = true
quote = true
style = Nodes::Scalar::PLAIN
tag = nil
str = o
if binary?(o)
str = [o].pack('m').chomp
tag = '!binary' # FIXME: change to below when syck is removed
#tag = 'tag:yaml.org,2002:binary'
style = Nodes::Scalar::LITERAL
plain = false
quote = false
elsif o =~ /\n/
style = Nodes::Scalar::LITERAL
elsif o == '<<'
style = Nodes::Scalar::SINGLE_QUOTED
tag = 'tag:yaml.org,2002:str'
plain = false
quote = false
elsif o =~ /^\W[^"]*$/
style = Nodes::Scalar::DOUBLE_QUOTED
else
unless String === @ss.tokenize(o)
style = Nodes::Scalar::SINGLE_QUOTED
end
end
ivars = find_ivars o
if ivars.empty?
unless o.class == ::String
tag = "!ruby/string:#{o.class}"
plain = false
quote = false
end
@emitter.scalar str, nil, tag, plain, quote, style
else
maptag = '!ruby/string'
maptag << ":#{o.class}" unless o.class == ::String
register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK)
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
@emitter.scalar str, nil, tag, plain, quote, style
dump_ivars o
@emitter.end_mapping
end
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 183
def visit_Struct o
tag = ['!ruby/struct', o.class.name].compact.join(':')
register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
o.members.each do |member|
@emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
accept o[member]
end
dump_ivars o
@emitter.end_mapping
end
# File psych/lib/psych/visitors/yaml_tree.rb, line 408
def visit_Symbol o
if o.empty?
@emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY
else
@emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
end
end
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.