Tbabs
Tbabs

Reputation: 445

How to revert/undo local changes to an Activerecord object?

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

Answers (3)

Peter Miller
Peter Miller

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

Jim
Jim

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

Philip Hallstrom
Philip Hallstrom

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

Related Questions