views:

95

answers:

2

I have an ActiveRecord model object Foo; it represents a standard database row.

I want to be able to display modified versions of instances of this object. I'd like to reuse the class itself, as it already has all the hooks & aspects I'll need. (For example: I already have a view that displays the appropriate attributes). Basically I want to clone the model instance, modify some of its properties, and feed it back to the caller (view, test, etc).

I do not want these attribute modifications getting back into the database. However, I do want to include the id attribute in the cloned version, as it makes dealing with the route-helpers much easier. Thus, I plan on calling ActiveRecord::Base.clone(), manually setting the ID of the cloned instance, and then making the appropriate attribute changes to the new instance. This has me worried though; one save() on the modified instance and my original data will get clobbered.

So, I'm looking to lock down the new instance so that it won't hurt anything else. I'm already planning on calling freeze() (on the understanding that this prevents further modification to the object, though the documentation isn't terribly clear). However, I don't see any obvious way to prevent a save().

What would be the best approach to achieving this?

+3  A: 

There might be a more idiomatic way to do this, but one way would be to set a virtual attribute and check it in a before_save callback. When you clone the object, set the virtual attribute – maybe something like is_clone to true. Then define a before_save callback for your model class that prevents the save if that attribute is set.

Jimmy Cuadra
+2  A: 

freeze() seems to be achieving what I want, though in an ugly way.

x = Factory.create(:my_model)
x.save!    # true
x.freeze
x.save!
TypeError: can't modify frozen hash

I'm guessing that save() is trying to update the created/modified attributes, which fails because the attributes hash is frozen.

So, freezing will prevent the saving... but I'd appreciate a more reliable method with a more specific error message.

Craig Walker