If an attribute is updated during an after_create callback, the attribute is not marked as dirty.
We've forked Rails and added a failing test for this issue (pivotal-ghostchips@9b2725f). However, before writing a fix, we'd like to confirm this is truly a bug and not expected behavior.
For convenience, here's the production code / failing test:
class ModelWithAfterCreateCallbacks < ActiveRecord::Base
self.table_name = 'developers'
NAME = "foo"
self.name = NAME
m = ModelWithAfterCreateCallbacks.create
assert_equal m.valid?, true
assert_equal ModelWithAfterCreateCallbacks::NAME, m.name
assert_equal m.changed_attributes.has_key?("name"), true
Surprisingly, m.changed? is false, and m.changed_attributes is empty, even though the name property has changed and not been persisted.
Attributes are only changed until before you save. Once it's saved all attributes are assumed to be the correct value, hence not dirty. If you change them again after saving, they will then be dirty again.
If the attributes in the ActiveModel instance are such that something is going to be updated in the db the next time #save is called, it seems like a bug. I would expect the AR::B attribute to be dirty in this case.
I agree with @jsl. This seems like a bug.
I think if it's a bug should not have sense the call_back before_validation and after_validation
the ActiveRecord::AttributeMethods::Dirty module is wrapped around save and save!. Since save triggers create eventually, the after_create callback is wrapped by save and therefore the dirty attributes are reset after the callback ran. I'm not sure if it is a bug or supposed to work the way it does.
@rafaelfranca @steveklabnik do you have any insights?
These kinds of problems make my head hurt, to be honest.
It is supposed to work this way. after_create callbacks run before after_save callbacks and the changes are reseted after the after_save callback to make possible to users use these changes values in the callbacks.