After_update attributes problem

Hey guys,

I’m having a hard time w/ the after_update callback on rails… As
far as I can tell, when I define a after_update callback on a model,
the attributes of the object have the same values that they had
before Base.save was called. I’m probably wrong so here’s the code:

UNIT TEST:
def test_register_item_adjusts_account_balance
account = accounts(:cams_credit_card)
transaction = RegisterItem.new(:date => ‘2006-10-31’,
:description => ‘Chinese food’,
:amount => ‘-13.44’)
transaction.account = account
transaction.save
assert_equal -113.44, account.balance #this assertion passes

transaction.amount = -15.50
transaction.save
assert_equal -115.50, account.balance  # FAILS

transaction.destroy
assert_equal -100.00, account.balance #this assertion will pass

end

FAILURE OUTPUT:
Loaded suite test/unit/register_item_test
Started
.F.
Finished in 0.202591 seconds.

  1. Failure:
    test_register_item_adjusts_account_balance(RegisterItemTest)
    [test/unit/register_item_test.rb:31]:
    <-115.5> expected but was
    <-113.44>.

3 tests, 6 assertions, 1 failures, 0 errors

So changing the amount on a transaction (RegisterItem) should change
the current balance of an account. Here’s the relevent callbacks:

REGISTER_ITEM UPDATE CALLBACKS:
def before_update
account.balance -= amount
account.save
end

def after_update
account.balance += amount
account.save
end

So the idea is that before the transaction is updated i subtract the
amount of the transaction back from the account, and then add the new
amount back on. It looks like @amount is still the old value during
the after_update callback though. is that correct? how can i access
the new value?

Thanks,
Cameron M.

the steps are:

before_update
[update operation]
after_update

so to keep things simple, say your account balance is 0.0:

existing transaction

transaction.amount = 10.0 # transaction.account.balance = 0.0 still

transaction.save

before_update: transaction.amount = 10.0,

transaction.account.balance = -10.0

update operation

after_update: transaction.amount = 10.0, transaction.account.balance

= 0.0

so you’re back where you started, which is what your test is telling
you.

Would calling account.reload after the save cause problems for you
elsewhere?

Cameron M. wrote:

Hey guys,

I’m having a hard time w/ the after_update callback on rails… As
far as I can tell, when I define a after_update callback on a model,
the attributes of the object have the same values that they had
before Base.save was called. I’m probably wrong so here’s the code:

Here’s the relevent callbacks:

REGISTER_ITEM UPDATE CALLBACKS:
def before_update
account.balance -= amount
account.save
end

def after_update
account.balance += amount
account.save
end

Hey Steve,

On 1/4/07, Steve K. [email protected] wrote:

Would calling account.reload after the save cause problems for you
elsewhere?

I wasn’t aware of the reload method. I called it after save and
although it didn’t cause any problems, it didn’t change the behavior
of the program either (unless i called self.reload on the transaction,
in which case it looks like the after_update callback didn’t get
called)

Thanks!
Cam

these are the callbacks that are run during an update operation

before_validation
before_validation_on_update
after_validation
after_validation_on_update
before_save
before_update

after_update
after_save

if you are creating a new record, replace *_update with *_create in
the above list. thats the difference.

so, knowing this, we see that your before and after updates will run
around the update operation.

transaction.account.balance = -100.00

transaction.amount = -15.50
transaction.save # before_update, update, after_update

before_update callback

-----------------------------------

account.balance -= amount

-100.00 - (-15.50) = -(100.00 - 15.50) = -84.50

account.save

transaction update operation

after_update callback

--------------------------------

account.balance += amount

-84.50 + (-15.50) = -(84.50 + 15.50) = -100.00

account.save

assert_equal -115.50, account.balance # FAILS

account.balance -= amount # 113.44, as 100.00 - (-13.44) = 100.00 + 13.44 = 113.44 account.save # balance of 113.44 is saved to db account.balance += amount # 100.00, as 113.44 + (-13.44) = 113.44 - 13.44 = 100.00 account.save # balance of 100.00 is saved to the db

and so you are right back where you started as far as your
account.balance goes, which is exactly what your test is telling you.

follow?

Chris

Hey thanks for the response:

On 1/4/07, Chris H. [email protected] wrote:

so to keep things simple, say your account balance is 0.0:

so you’re back where you started, which is what your test is telling you.
Ok so there is a problem in the way i understand the before_update
callback, or in your logic (probably my problem which would explain
the bug). Anyway, this is a before/after_update callback, it looks
like the scenario you’re describing is a before/after_create kind of
deal. so the way i would understand it would be like so:

#account.balance == 0
transaction.amount = 10.0 #transaction.amount formerly == 0
before_update: transaction.amount -= 0
after_update: transaction.amount += 10

account.balance == 10

is that wrong?
Cameron M.

hey,

On 1/16/07, Chris H. [email protected] wrote:

follow?

it makes sense… i hadn’t understood how it worked previously. i
figured that since it was before save was called, that the data would
have been the old data. so is there no way to access the previous
data w/ callbacks? i guess i could store the old amount in all of the
RegisterItem model, but i’d rather not go that route.

thanks,
cam