Reputation: 445
Is there a way to undo/revert any local changes to an Activerecord object. For example:
user = User.first
user.name # "Fred"
user.name = "Sam"
user.name_was # "Fred"
user.revert
user.name # "Fred"
I know I could do user.reload
but I shouldn't have to hit the database to do this since the old values are stored in the state of the object.
Preferably a Rails 3 solution.
Upvotes: 18
Views: 10944
Reputation: 441
As mentioned in this answer Rails 4.2 introduced the restore_attributes
method in ActiveModel::Dirty
:
user = User.first
user.name # "Fred"
user.status # "Active"
user.name = "Sam"
user.status = "Inactive"
user.restore_attributes
user.name # "Fred"
user.status # "Active"
If you want to restore a specific attribute, restore_<attribute_name>!
can be used, such as restore_name!
:
user.name = "Sam"
user.status = "Inactive"
user.restore_name!
user.name # "Fred"
user.status # "Inactive"
Upvotes: 34
Reputation: 1062
In case anyone ends up here, restore_attributes is the way to do it as of rails 4.2:
http://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-restore_attributes
Upvotes: 24
Reputation: 19889
You could just loop through the 'changes' and reset them. There might be a method that does this, but I didn't look.
> c = Course.first
> c.name
=> "Athabasca Country Club"
> c.name = "Foo Bar"
=> "Foo Bar"
> c.changes
=> {"name"=>["Athabasca Country Club", "Foo Bar"]}
> c.changes.each {|k,vs| c[k] = vs.first}
> c.name
=> "Athabasca Country Club"
Actually looks like there is a "name_reset!" method you could call...
> c.changes.each {|k,vs| c.send("#{k}_reset!")}
Upvotes: 9