Rails - Get old value in before_save
Asked Answered
C

4

20

I'm trying to get the old value in the before_save by adding "_was" to my value but it doesn't seem to work.

Here is my code:

before_save :get_old_title

def get_old_title
    puts "old value #{self.title_was} =>  #{self.title}"
  end

Both "title_was" and "title" got the new title just been saved.

Is it possible to get the old value inside before_save ?

Coleencolella answered 6/4, 2015 at 4:38 Comment(8)
Are you trying to get old value before you update the same row data?Nard
yes, lets say my old value was "batman" and changed it to "superman", I want to get "batman"Coleencolella
Instead of before_save use before_updateNard
Also read up on ActiveModel::Dirty and check out the examplesEspouse
What you are doing is absolutely correct. can you paste your controller code also.Recrystallize
@Nard I changed before_save to before_update and it works now. Create an answer, so I can accept it. :)Coleencolella
I agree with @architgupta. It seems correct. I don't understand why before_save wouldn't work.Puny
@Coleencolella Can you show controller code. It seems you are not calling save method inside the controller, rather calling update . This is the only reason, before_save callback didn't work.Puny
N
12

Instead of before_save use before_update. It should work now.

Nard answered 6/4, 2015 at 5:16 Comment(4)
before_save called at the time of object creation(only one time) and before_update calls every time when object is updated.Faille
@SachinR you are wrong. before_save is called on update as well as on creation and before_update_is called only on update. Check this #18471249Recrystallize
The answer doesn't give correct answer to the question whether it is possible to get the old value inside before_save (it IS) and changing before_save to before_update is only a workaround for a specific case.Chammy
Did not work for me as before_update was called before before_save when updating a record, this corresponds to the order in guides.rubyonrails.org/…. The answer of talal7860 worked well for me, using the [attr]_changed? and [attr]_was methods of ActiveModel::Dirty.Adnate
C
14

The reason for you getting the same value is most probably because you check the output when creating the record. The callback before_save is called on both create() and update() but on create() both title and title_was are assigned the same, initial value. So the answer is "yes, you can get the old value inside before_save" but you have to remember that it will be different than the current value only if the record was actually changed. This means that the results you are getting are correct, because the change in question doesn't happen when the record is created.

Chammy answered 9/3, 2017 at 20:14 Comment(0)
N
12

Instead of before_save use before_update. It should work now.

Nard answered 6/4, 2015 at 5:16 Comment(4)
before_save called at the time of object creation(only one time) and before_update calls every time when object is updated.Faille
@SachinR you are wrong. before_save is called on update as well as on creation and before_update_is called only on update. Check this #18471249Recrystallize
The answer doesn't give correct answer to the question whether it is possible to get the old value inside before_save (it IS) and changing before_save to before_update is only a workaround for a specific case.Chammy
Did not work for me as before_update was called before before_save when updating a record, this corresponds to the order in guides.rubyonrails.org/…. The answer of talal7860 worked well for me, using the [attr]_changed? and [attr]_was methods of ActiveModel::Dirty.Adnate
C
7

So, the answer above might work but what if I wanted to get the previous value for some reason and use it to perform some task then you would need to get the previous value. In my case I used this

after_update do
  if self.quantity_changed?
    sku.decrement(:remaining, (self.quantity_was - self.quantity) * sku.quantity)
  end
end

The _was and _changed? added to any of the columns would do the job to get the job done.

Calves answered 26/2, 2017 at 23:47 Comment(1)
When writing my tests. I found out that I had to use before_update otherwise, there was no difference between 'quantity' and 'quantity_was'Womenfolk
I
1

In rails 5.1.1 ActiveRecord::AttributeMethods::Dirty provides

saved_changes()

Link for saved_changes() which returns a hash containing all the changes that were just saved.

Ingeminate answered 8/7, 2022 at 7:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.