defining a custom to_yaml method to inline hashes

A

Ara.T.Howard

check out the following:


jib:~ > cat a.rb
require 'yaml'

# yaml can load inline hashes
inline_hash = YAML::load "--- { jid: 121, metric: started, time: 2005-05-10 08:18:22.523016 }"

puts '=' * 8
y inline_hash
puts


# attempt to bludgeon to object into emitting in an inline fashion
class << inline_hash
def to_yaml(*a, &b)
'{ ' << map{|kv| kv.join(': ')}.join(', ') << ' }'
end
end

# looks good at first
puts '=' * 8
y inline_hash
puts

# but doesn't really work after all when part of another object
puts '=' * 8
y({'running' => inline_hash})
puts


jib:~ > ruby a.rb
========
---
time: 2005-05-10 08:18:22.523016
jid: 121
metric: started

========
{ time: 2005-05-10 08:18:22.523016, jid: 121, metric: started }

========
---
running:


notice the second block is alright but the third is not. i know i need to do
something like

def to_yaml(*a, &b)
YAML::quick_emit(*a, &b) do |out|
# now what?
end
end


but can't seem to find anything in the docs or samples.

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
A

Ara.T.Howard

check out the following:


jib:~ > cat a.rb
require 'yaml'

# yaml can load inline hashes
inline_hash = YAML::load "--- { jid: 121, metric: started, time: 2005-05-10
08:18:22.523016 }"

puts '=' * 8
y inline_hash
puts


# attempt to bludgeon to object into emitting in an inline fashion
class << inline_hash
def to_yaml(*a, &b)
'{ ' << map{|kv| kv.join(': ')}.join(', ') << ' }'
end
end

# looks good at first
puts '=' * 8
y inline_hash
puts

# but doesn't really work after all when part of another object
puts '=' * 8
y({'running' => inline_hash})
puts


jib:~ > ruby a.rb
========
---
time: 2005-05-10 08:18:22.523016
jid: 121
metric: started

========
{ time: 2005-05-10 08:18:22.523016, jid: 121, metric: started }

========
---
running:


notice the second block is alright but the third is not. i know i need to do
something like

def to_yaml(*a, &b)
YAML::quick_emit(*a, &b) do |out|
# now what?
end
end

but can't seem to find anything in the docs or samples.

this seems o.k. - can anyone verify this is an o.k. approach?

jib:~ > cat a.rb
require 'yaml'
class Hash
def yaml_inline= bool
unless defined? @__yaml_inline_meth
@__yaml_inline_meth =
lambda {|opts|
YAML::quick_emit(id, opts) {|emitter|
emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
}
}
class << self
def to_yaml opts = {}
@__yaml_inline ? @__yaml_inline_meth[ opts ] : super
end
end
end
@__yaml_inline = bool
end
end


hash = { 'jid' => 121, 'metric' => 'started', 'time' => '2005-05-10 08:18:22.523016' }


y 'hash' => hash
puts

hash.yaml_inline = true
y 'hash' => hash
puts

hash.yaml_inline = false
y 'hash' => hash
puts


jib:~ > ruby a.rb
---
hash:
time: 2005-05-10 08:18:22.523016
jid: 121
metric: started

---
hash: { time: 2005-05-10 08:18:22.523016, jid: 121, metric: started }

---
hash:
time: 2005-05-10 08:18:22.523016
jid: 121
metric: started


of course this only works with kvs as strings....

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
W

why the lucky stiff

Hacking Syck 0.45 or less will be very involved. Consider that inline
collections must also contain inline hashes and inline arrays. And, as
your sample code demonstrated, some strings which get formatted in the
"folded" or "literal" block styles won't jive with inlines.

Syck 0.53 and up is a different story. You can easily emit inlines by
defining a `to_yaml_style' method.
=> ---
{ time: 2005-05-10 08:18:22.523016, jid: 121, metric: started }

The new Syck emitter will ensure that everything inside the inline is
properly output. I still need to improve the pretty printer, but it
works.
this seems o.k. - can anyone verify this is an o.k. approach?

jib:~ > cat a.rb
require 'yaml'
class Hash
def yaml_inline= bool
unless defined? @__yaml_inline_meth
@__yaml_inline_meth =
lambda {|opts|
YAML::quick_emit(id, opts) {|emitter|
emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
}
}
class << self
def to_yaml opts = {}
@__yaml_inline ? @__yaml_inline_meth[ opts ] : super
end
end
end
@__yaml_inline = bool
end
end

This will work for very simple hashes, but will break down upon
encountering multiline strings or any kind of object, array, hash, etc.

While Syck 0.5x isn't ready for primetime, it's getting very close. I
could use help debugging and the time you spend debugging could yield a
stable Syck in the next two months.

_why
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,476
Latest member
blackwatermelon

Latest Threads

Top