Hello people. Today I've found a bug in my source code, been around for a while until I realized of the problem, here is a bit of code which represent it: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* class A def initialize @var_a = 50 end end class B attr_accessor :var_b def initialize(value) @var_b = value end end a = A.new b = B.new(a) #I 'marshal' both of the variables #Then close the app, open it and load again their state, so I expect #that the next snippet is true: p b.var_b.==(a) #=> false #They are differents objects and I don't need that. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* So how do you think that I can resolve this problem? Been thinking for a solution but I'm not sure about... I'll appreciate your help, thank you very much. Damián.
on 2013-03-06 15:32
on 2013-03-06 15:51
how do you marshal them? if you marshal them in ONE step it can solve your circle
on 2013-03-06 16:57
Good question. See, I marshal them in differents times. Because I don't have to persist lot of information I don't use any database like MySQL, I just save the object in binary files(by marshaling). The application have a GUI, so when a user do some thing certain object is persisted, that object is pointing to other objects, like the example of @var_b. The problem is that when I regenerate the objects, the shown above happen. When in some part of the source code I have to compare in the way above the are not equals: b.var_b.inspect #=> <A:0x0145A4> a.inspect #=> <A:0x457D78> They are not the same, perhaps(meaby an obvious thing) because Marshal reconstruct the object just by looking their atributes saved but Marshal doesn't bother about create the same object that another that will be created with the same attributes. Am I right? I have to add that I persist them in differents files. I've realized(meaby) what you mean: You mean persist both object in ONE step like put them into an #Array and then persist the Array? Well that meaby can solve the problem, but the meaning of persist the object in different steps and differents files is that isn't the same persist 1K of information(one object) than persist the whole model, like 50 objects at the same time. I didn't see the sense of that because the application is just changing one object when the user do a certain movement in the GUI, not the 50, so I didn't see the sense in save the whole model.
on 2013-03-06 17:33
On Wed, Mar 6, 2013 at 4:58 PM, Damin M. Gonzlez <lists@ruby-forum.com> wrote: > b.var_b.inspect > #=> <A:0x0145A4> > a.inspect > #=> <A:0x457D78> > > They are not the same, perhaps(meaby an obvious thing) because Marshal > reconstruct the object just by looking their atributes saved but Marshal > doesn't bother about create the same object that another that will be > created with the same attributes. Am I right? Marshal retains an idea of identity only during _one_ write operation. So it will reconstruct graphs properly if you ensure all interesting instances are referenced from a single instance. As Hans said: do it in one step for example by placing both in an Array: irb(main):016:0> x, y = Marshal.load(Marshal.dump([a,b])) => [#<A:0x802ba284 @var_a=50>, #<B:0x802ba248 @var_b=#<A:0x802ba284 @var_a=50>>] irb(main):017:0> x.equal? y.var_b => true In your case it would also be sufficient to only marshal b because that references a already and there is an easy way to access it after deserialization. Kind regards robert
on 2013-03-06 18:35
> Marshal retains an idea of identity only during _one_ write operation. > So it will reconstruct graphs properly if you ensure all interesting > instances are referenced from a single instance. I can now clearly see what you say. > As Hans said: do it in one step for example by placing both in an Array: > > irb(main):016:0> x, y = Marshal.load(Marshal.dump([a,b])) > => [#<A:0x802ba284 @var_a=50>, #<B:0x802ba248 @var_b=#<A:0x802ba284 > @var_a=50>>] > irb(main):017:0> x.equal? y.var_b > => true Yes, it's what I say above > In your case it would also be sufficient to only marshal b because > that references a already and there is an easy way to access it after > deserialization. I understand what you say, but my model is far more complex, I have many objects with atributtes pointing to anothers objects from differents clases, it's not so simple. At now the only way that I see is: in some way try to reconstruct the objects manually, for example, many of my classes will have only one instance at time in the model, so I can do something like this(referencing the above example): -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- #supposing that before I've loaded the state of ::A1 which is the state #of the above a variable #monkeypatch class B def marshal_dump [@var_b] end #Note: I have all the only-one-instance-per-class pointed by a #constant in the main scope(don't know if this is a good way just #implemented in that way)) def marshal_load(attributes) @var_b = (if attributes[0].is_a?(A) then ::A1 else attributes[0] end) end end -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- Do you think that exist a better and faster way than this to treat with the problem? I'll appreciate your help, thanks.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.