Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Doing fixups after deserializing YAML

1 view
Skip to first unread message

Matthew Westcott

unread,
May 20, 2005, 5:36:20 PM5/20/05
to
Hi,
Suppose (for reasons best known to myself) I had the following code:

require 'yaml'

class Squarer
attr_reader :num, :num_squared

def initialize(num)
@num = num
@num_squared = num * num
end

def to_yaml_properties
# no need to store both num and num_squared...
%w{ @num }
end
end

s = Squarer.new(42)
yaml_s = YAML.dump(s)

new_s = YAML.load(yaml_s)
puts "new_s.num = #{new_s.num}"
puts "new_s.num_squared = #{new_s.num_squared}"


Is there any way I can hook up a bit of fixup code to set @num_squared
appropriately after deserializing from YAML? If I were using Marshal,
I'd just override the marshal_load method - what (if anything) is the
YAML equivalent?

- Matthew

Logan Capaldo

unread,
May 21, 2005, 7:52:30 PM5/21/05
to

Well this solution doesn't involve yaml but...

class Squarer
def num_squared
@num_squared ||= @num * @num
end
end

So it will calculate it only the first time you ask for it.


Matthew Westcott

unread,
May 24, 2005, 6:19:28 PM5/24/05
to
Logan Capaldo wrote:
> On 5/20/05, Matthew Westcott <gas...@raww.org> wrote:
>
>>class Squarer
>> attr_reader :num, :num_squared
>>
>> def initialize(num)
>> @num = num
>> @num_squared = num * num
>> end
>>end

[serialising / deserialising a Squarer object to YAML without writing
the @num_squared variable]

> Well this solution doesn't involve yaml but...
>
> class Squarer
> def num_squared
> @num_squared ||= @num * @num
> end
> end
>
> So it will calculate it only the first time you ask for it.

Hi,
Thanks very much for the suggestion - as you might expect, though, the
example I gave was drastically simplified from the real-life problem I
was stuck on. In that situation, it just wasn't feasible to eliminate
all redundant internal state from the object itself - but I rather
wanted to eliminate it from the object's YAML representation, at least.

In the end I found the bit of documentation I was after
<http://yaml4r.sourceforge.net/doc/page/type_families.htm> , and arrived
at this solution:

require 'yaml'

class Squarer
attr_reader :num, :num_squared

def initialize(num)
@num = num
@num_squared = num * num
end

def to_yaml_type
# register this as a custom type
"!west.co.tt,2005-05-24/squarer"
end

def to_yaml_properties
%w{ @num }
end
end

# tell the YAML parser how to deal with an object of this type
YAML.add_domain_type( "west.co.tt,2005-05-24", "squarer" ) { |type, val|
# val is a hash of all the fields we serialised (i.e. just @num)
Squarer.new(val['num'])

# here we'd do any more initialisation of the object
# if necessary
}

0 new messages