yaml object de-serialisation

U

Une bévue

i've a class "Preferences"
which includes other classes for example "Theme"

i save an instance of "Preferences" by writing self.to_yaml into a file.

obviously, i want to retrive this instance back by :
o=YAML::load(File.open("#{PREFS_FILE}"))

PREFS_FILE being the preceedingly saved one.

what's the best way to "re-populate" my classes ?

for the time being i'm doing :

o.themes_list.each { |theme|
t=Theme.new(theme.label)
t.nb_cols_list=theme.nb_cols_list
@themes_list << t
}
[...]
@theme_label=o.theme_label
@nb_cols=o.nb_cols


does exist a more direct way to do the samething ?
 
D

David Vallner

D=C5=88a =C5=A0tvrtok 09 Febru=C3=A1r 2006 12:48 Une b=C3=A9vue nap=C3=ADsa=
l:
i've a class "Preferences"
which includes other classes for example "Theme"

i save an instance of "Preferences" by writing self.to_yaml into a file.

obviously, i want to retrive this instance back by :
o=3DYAML::load(File.open("#{PREFS_FILE}"))

PREFS_FILE being the preceedingly saved one.

what's the best way to "re-populate" my classes ?

for the time being i'm doing :

o.themes_list.each { |theme|
t=3DTheme.new(theme.label)
t.nb_cols_list=3Dtheme.nb_cols_list
@themes_list << t
}
[...]
@theme_label=3Do.theme_label
@nb_cols=3Do.nb_cols


does exist a more direct way to do the samething ?

I thought YAML does deep serialization? It should load this automatically.

What do you mean by Preferences including Themes? If you mean instances of=
=20
Theme are instance variables of Preferences, or are stored in an Array in=20
Preferences, you shouldn't need to repopulate anything.

I didn't quite understand the intent of your code, but it looks like you're=
=20
doing copies of themes from o.themes_list to another Array @themes_list...=
=20
Why can't you keep them in the original object "o" and access them from=20
there?

David Vallner
 
U

Une bévue

First, thanks for your reply ))
What do you mean by Preferences including Themes? If you mean instances of
Theme are instance variables of Preferences, or are stored in an Array in
Preferences, you shouldn't need to repopulate anything.
yes i have another class Theme and Preferences class includes an array
of instances of Theme.
I didn't quite understand the intent of your code, but it looks like you're
doing copies of themes from o.themes_list to another Array @themes_list...
Why can't you keep them in the original object "o" and access them from
there?

ok, i see xhat you mean.

three cases :

- first launch of this app whithout any prefs saved:

i create a default prefs by :

prefs=Preferences.new blahblahblah

prefs.save #ie to a yaml file

- not first launch of this app with an instance of Preferences saved :

prefs=YAML::load(File.open("#{PREFS_FILE}"))

that's all


now the third case i've an old way to save prefs into a yaml file,
basically a hash instead of an instance of Preferences

in that case i only have to add another method to the Preferences class,
saying :

prefs=Preferences.new
prefs.updateFromOlderFileStructure

prefs.save

again, that's all.

am i right ?
 
D

David Vallner

D=C5=88a =C5=A0tvrtok 09 Febru=C3=A1r 2006 14:38 Une b=C3=A9vue nap=C3=ADsa=
l:
now the third case i've an old way to save prefs into a yaml file,
basically a hash instead of an instance of Preferences

in that case i only have to add another method to the Preferences class,
saying :

prefs=3DPreferences.new
prefs.updateFromOlderFileStructure

prefs.save

again, that's all.

am i right ?

Ah, this third case wasn't quite obvious from your example. But yes, you're=
=20
stuck to adapting the old preference structure to the new more or less by=20
hand. This doesn't seem like a particularly error prone piece of code, so I=
'd=20
stick with whatever seems to work for now, direct or indirect. As long as i=
t=20
works...

You could possibly golf down your script by having the new Theme object tak=
e=20
as constructor parameters the whole old corresponding object, but I don't=20
quite like this sort of coupling of compatibility code in the main logic.

David Vallner
 
U

Une bévue

David Vallner said:
You could possibly golf down your script by having the new Theme object take
as constructor parameters the whole old corresponding object, but I don't
quite like this sort of coupling of compatibility code in the main logic.

that's a "small" prob to me, i've used java where i might have multiple
constructors...

now to workaround i have build an initialize which returns all of its
attributes to nil or the like ([] in case of arrays)

a defaults method which populate de prefs with default values

an updateFromHash(o) which updates prefs from older structure.

suppose now, in the live of this app, i'll add some new attributes to
the class Preferences, what is the behaviour of yaml in that case ?

i suppose the new attributes (if an instance of Preferences is loaded
from older attributes list) will be nill ?
 
D

David Vallner

D=C5=88a =C5=A0tvrtok 09 Febru=C3=A1r 2006 15:33 Une b=C3=A9vue nap=C3=ADsa=
l:
that's a "small" prob to me, i've used java where i might have multiple
constructors...

Constructors are just cleverly disguised initializers. Have #initialize onl=
y=20
do the completely common code, and then explicitly call other initializer=20
methods you define if you want this pattern. I personally consider method=20
overloading a slight misfeature of the C++ language family, and have grown=
=20
quite accustomed to using the more flexible "options hash" pattern instead.=
=20
=46or example, if you have some class with instance variables bar, baz, and=
=20
quux:

class Foo
DEFAULTS =3D {
:bar =3D> 1,
:baz =3D> 2,
:quux =3D> 3
}
=09
attr :bar
attr :baz
attr :quux

def initialize(params)
attribs =3D DEFAULTS.dup.update(params)
@bar =3D attribs[:bar]
@baz =3D attribs[:baz]
@quux =3D attribs[:quux]
end
end

foo =3D Foo.new:)bar =3D "Hello", :quux =3D> "World")

p foo # Outputs #<Foo:0xb7c8004c @bar=3D"Hello", @quux=3D"World", @baz=3D2>

I find this covers 90% of what you commonly use overloaded constructors for=
,=20
and is a bit more readable too.
now to workaround i have build an initialize which returns all of its
attributes to nil or the like ([] in case of arrays)

a defaults method which populate de prefs with default values

an updateFromHash(o) which updates prefs from older structure.

If the above pattern doesn't cover what you need, you can always create mor=
e=20
factory methods to crunch for example the old structure into one the=20
constructor will like better.
suppose now, in the live of this app, i'll add some new attributes to
the class Preferences, what is the behaviour of yaml in that case ?

i suppose the new attributes (if an instance of Preferences is loaded
from older attributes list) will be nill ?

Yes, the YAML loader doesn't know anything about what instance attributes t=
he=20
object is supposed to have. AFAIK, it uses Object::allocate to create a bla=
nk=20
instance of the class, then populates the instance variables via=20
Object#instance_variable_set, or something equivalent.
 
J

Joel VanderWerf

Une said:
i've a class "Preferences"
which includes other classes for example "Theme"
=20
i save an instance of "Preferences" by writing self.to_yaml into a file=
 
M

Mark Volkmann

have grown
quite accustomed to using the more flexible "options hash" pattern instea= d.
For example, if you have some class with instance variables bar, baz, and
quux:

class Foo
DEFAULTS =3D {
:bar =3D> 1,
:baz =3D> 2,
:quux =3D> 3
}

attr :bar
attr :baz
attr :quux

def initialize(params)
attribs =3D DEFAULTS.dup.update(params)
@bar =3D attribs[:bar]
@baz =3D attribs[:baz]
@quux =3D attribs[:quux]
end
end

foo =3D Foo.new:)bar =3D "Hello", :quux =3D> "World")

p foo # Outputs #<Foo:0xb7c8004c @bar=3D"Hello", @quux=3D"World",= @baz=3D2>

I find this covers 90% of what you commonly use overloaded constructors f= or,
and is a bit more readable too.

I'd never seen this before. Cool!

I think you can use
attribs =3D DEFAULTS.merge(param)
instead of
attribs =3D DEFAULTS.dup.update(params)
 
U

Une bévue

David Vallner said:
If the above pattern doesn't cover what you need, you can always create more
factory methods to crunch for example the old structure into one the
constructor will like better.

yes, that's another solution. I'll think about your above solution
(options hash) because i don't like the way i've done that actually
mostly because, i, my case, the #initialize is more orl es a fake
initialise : it returns somehow an empty object.
Yes, the YAML loader doesn't know anything about what instance attributes the
object is supposed to have. AFAIK, it uses Object::allocate to create a blank
instance of the class, then populates the instance variables via
Object#instance_variable_set, or something equivalent.

OK, thanks for all.
 
D

David Vallner

D=C5=88a =C5=A0tvrtok 09 Febru=C3=A1r 2006 22:12 Mark Volkmann nap=C3=ADsal:
I'd never seen this before. Cool!

I saw this on some page about ruby idioms somewhere. Might have been the=20
RubyGarden one. Or the RAA library interface design guidelines. I think tho=
se=20
are very roughly a ripoff from Perl's, and I don't necessarily like them, a=
nd=20
I didn't like this idiom at first. But then I saw this other snippet where=
=20
the default parameters were used and suddenly it made Perfect Sense (tm).=20


This is used all over the place in Rails, and the options hash is useful=20
outside constructors too. I find it generally both more readable and=20
comfortable to use than having multiple methods accept different combinatio=
ns=20
of parameters, especially since you get the perks of keyword arguments=20
(arbitrary argument order) along. You might want to check for typos by bein=
g=20
strict about what keys / combinations of keys you accept in the options has=
h,=20
and convert the keys to symbols or vice versa depending on what you except.
I think you can use
attribs =3D DEFAULTS.merge(param)
instead of
attribs =3D DEFAULTS.dup.update(params)

*bangs head against wall*

I should really, really start reading ri output better. I knew about=20
Hash#update, but I didn't actually go on and notice it's a synonym for=20
Hash#merge! when I checked ri. D'oh!

David Vallner
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top