The #new_record? function determines if a record has been saved. But it is always false in the after_save
hook. Is there a way to determine whether the record i
For Rails 4 (checked on 4.2.11.1) results of changes
and previous_changes
methods are empty hashes {}
on object creation inside after_save
. So attribute_changed?
methods like id_changed?
won't work as expected.
But you can take advantage of this knowledge and - knowing that at least 1 attribute has to be in changes
on update - check if changes
is empty. Once you confirm that it's empty, you must be during object creation:
after_save do
if changes.empty?
# code appropriate for object creation goes here ...
end
end
No rails magic here that I know of, you'll have to do it yourself. You could clean this up using a virtual attribute...
In your model class:
def before_save
@was_a_new_record = new_record?
return true
end
def after_save
if @was_a_new_record
...
end
end
I was looking to use this for an after_save
callback.
A simpler solution is to use id_changed?
(since it won't change on update
) or even created_at_changed?
if timestamp columns are present.
Update: As @mitsy points out, if this check is needed outside of callbacks then use id_previously_changed?
. See docs.
Since the object has already been saved, you would you need to look at the previous changes. The ID should only change after a create.
# true if this is a new record
@object.previous_changes[:id].any?
There is also an instance variable @new_record_before_save
. You can access that by doing the following:
# true if this is a new record
@object.instance_variable_get(:@new_record_before_save)
Both are pretty ugly, but they would allow you to know whether the object has been newly created. Hope that helps!
There is an after_create
callback which is only called if the record is a new record, after it is saved. There is also an after_update
callback for use if this was an existing record which was changed and saved. The after_save
callback is called in both cases, after either after_create
or after_update
is called.
Use after_create
if you need something to happen once after a new record has been saved.
More info here: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
I like to be specific even I aware that :id
shouldn't change in normal, but
(byebug) id_change.first.nil?
true
It always cheaper to be specific instead finding very weird unexpected bug.
The same way if I expect true
flag from untrustworthy argument
def foo?(flag)
flag == true
end
This saves a lot of hours to not sitting on weird bugs.