[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Doing fixups after deserializing YAML

Matthew Westcott

5/20/2005 9:36:00 PM

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
2 Answers

Logan Capaldo

5/21/2005 11:53:00 PM

0

On 5/20/05, Matthew Westcott <gasman@raww.org> wrote:
> 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
>
>

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

5/24/2005 10:19:00 PM

0

Logan Capaldo wrote:
> On 5/20/05, Matthew Westcott <gasman@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_famili... , 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
}