misunderstanding the Passing of references

T

Todd S.

I'm to to ruby...

Currently, I'm stuck in a situation where I'm changing values I'm not
intending to and I don't know how to correct it.

I have... A class "Model" and a class "DataObject". The "Data Object"
class has a method which takes in a "Model" and returns a new "Model".
The problem is, my "generate_new_model" method is altering the input
"Model" object.

The below show basically what I've done to create the objects. Somehow
when I define a new "Model" for output and set it's values to the source
model's values, when I change the outputModel values it alters the
source model.

What am I doing wrong?


@myModel = Model.new
@myData = DataObject.new

newModel = @myData.generate_new_model(@myModel)


def generate_new_model(modelSource)
outputModel = Model.new
outputModel = modelSource

outputModel.values = "new values"

outputModel
end
 
M

Matthew Smillie

@myModel = Model.new
@myData = DataObject.new

newModel = @myData.generate_new_model(@myModel)


def generate_new_model(modelSource)
outputModel = Model.new

So far, so good. At the minute, outputModel references a brand new
Model.
outputModel = modelSource

Now, however, it references the same model as modelSource. Oops.
outputModel.values = "new values"

And here you've changed the values of the Model referenced by
outputModel and modelSource.
outputModel
end


Am I right in guessing that you're trying to put a copy of
modelSource into outputModel? If so, you might want to take a look
at this:

http://www.rubygarden.org/ruby?Make_A_Deep_Copy_Of_An_Object

Depending on the structure of the Model class, it might be better to
give it its own copy method.

matthew smillie.
 
T

Todd S.

Am I right in guessing that you're trying to put a copy of
modelSource into outputModel?

That's exactly the case. In reading the link you suggest it seems I
would have to use a seperate data dumping operation. This seems a
little strange to me. Shouldn't there be a more simple way to create a
copy of an object?
 
T

Todd S.

Just to provide some direct information for anyone who might find this
and need the help...

The below does indeed solve the problem...

class Model
def deep_clone
Marshal::load(Marshal.dump(self))
end
end

a = Model.new
b = Model.deep_clone

Thank you very much for your help.
 
M

Matthew Smillie

In reading the link you suggest it seems I
would have to use a seperate data dumping operation. This seems a
little strange to me. Shouldn't there be a more simple way to
create a
copy of an object?

There is and there isn't: Object#dup and #clone both make shallow
copies:
http://ruby-doc.org/core/classes/Object.html#M001067

There's no built-in method to create deep copies of any object,
though, and the serialise/unserialise thing just hacks around that in
the quickest way (as in, quickest to write).

If it were me, unless the Model class was extraordinarily
complicated, I'd probably just write my own copy method.

matthew smillie.
 
R

Robert Klemme

Matthew said:
There is and there isn't: Object#dup and #clone both make shallow
copies:
http://ruby-doc.org/core/classes/Object.html#M001067

There's no built-in method to create deep copies of any object,
though, and the serialise/unserialise thing just hacks around that in
the quickest way (as in, quickest to write).

If it were me, unless the Model class was extraordinarily
complicated, I'd probably just write my own copy method.

You can as well override or reimplement the #dup method.

robert
 
L

Logan Capaldo

Just to provide some direct information for anyone who might find this
and need the help...

The below does indeed solve the problem...

class Model
def deep_clone
Marshal::load(Marshal.dump(self))
end
end

a = Model.new
b = Model.deep_clone

Thank you very much for your help.

This isn't perfect but:
class Object
def deeper_copy
copy = self.dup
self.instance_variables.each do |ivar|
copy.instance_variable_set(ivar,
self.instance_variable_get(ivar).dup)
end
copy
end
end

Note that this is specifically designed to work for regular style
classes (ie ones that store everything in instance variables) and
for Strings, Arrays and Structs its no better than (but no worse
than) #dup. Hence "deeper_copy" instead of "deep_copy"
 

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
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top