Sam 山
Sam 山

Reputation: 42865

Rails: attribute_changed?

I have a model that has an amount and I'm tracking to see if this amount is changed with a Model.amount_changed? with a before_save which works fine but when I check to see amount_was and amount_change? it only returns the updated amount not the previous amount. And all this is happening before it is save. It knows when the attribute is changed but it will not return the old value.

Ideas?

class Reservation < ActiveRecord::Base

before_save  :status_amount, :if => :status_amount_changed

def status_amount_changed
  if self.amount_changed? && !self.new_record?
    true
  else
    false
  end
end

def status_amount
    title = "Changed Amount"
    description = "to #{self.amount_was} changed to #{self.amount} units"
    create_reservation_event(title, description)
end

def create_reservation_event(title, description)
    Event.create(:reservation => self, :sharedorder => self.sharedorder, :title => title,     :description => description, :retailer => self.retailer )
end

end

Upvotes: 11

Views: 11809

Answers (3)

microspino
microspino

Reputation: 7781

If you want to keep track of changes in your model Rails provides "Dirty Objects". E.g. Your model has a name attribute:

my_model = MyModel.find(:first)
my_model.changed?  # it returns false

# You can Track changes to attributes with my_model.name_changed? accessor
my_model.name  # returns  "Name"
my_model.name = "New Name"
my_model.name_changed? # returns true

# Access previous value with name_was accessor
my_model.name_was  # "Name"

# You can also see both the previous and the current values, using name_change
my_model.name_change  #=> ["Name", "New Name"]

If you want to store the old value inside your database, you can use:

  1. the model attribute amount
  2. the method _was on the above attribute in other words: amount_was that retrieve the value of amount before the change.

You can save both during the update_attributes call. Otherwise, if you don't need the amount_was history, you can just use two instance variables.

If you need somthing more, like tracking your model history, Rails has a nice dedicated plugin. As for other nice topics Ryan Bates speak about I here: Railscasts #177

Upvotes: 34

Harish Shetty
Harish Shetty

Reputation: 64363

Use *_was call to get the old value:

p m.amount_was if m.amount_changed?

Upvotes: 4

sameera207
sameera207

Reputation: 16619

You can create another vertual attribute in your module

attr_accessor :initial_amount

and when you are loading data from DB, fill the initial_amount with amount

then you can check

(initial_amount == amount ? true : false)

cheers, sameera

Upvotes: 0

Related Questions