This gem addresses an issue in ActiveRecord with the
saved_changes value when a record is updated multiple times in a single database transaction.
After a record is saved, you can check the set of changes with the
saved_changes method using the ActiveModel::Dirty API. However, when a record is saved multiple times, the list of saved changes is reset with each save operation. This can be an issue inside of an
before_commit callback since those callbacks are only called once for the transaction and will only get the last set of changes.
This can be a problem if you have a callback that checks for changes to specific fields. Consider this model where we want to run an asychronous job when a user changes their email address:
class User < ApplicationRecord after_commit :notify_email_changes, if: :email_changed? def notify_email_changes NotifyEmailChangesJob.perform_later(id) end end
This breaks down if a record is saved twice in a single transaction.
user.transaction do user.update!(email: params[:email]) if user.last_visited_at < 1.day.ago user.update!(last_visited_at: Time.now) end end
In the case where we update the
last_visited_at field, the
email_changed? method will return false since the email address was not changed in the last save operation and
notify_email_changes method will not be called.
This gem addresses this issue by merging all saved changes together before calling the
before_commit callbacks so that
saved_changes will return the complete list of changes for the transaction.
To use the gem, you simply need to mix it into your models. You can include it in all models by including it in your
class ApplicationRecord < ActiveRecord::Base include AfterCommitChanges end
Add this line to your application's Gemfile:
Or install it yourself as:
$ gem install gem "after_commit_changes"
Open a pull request on GitHub.
Please use the standardrb syntax and lint your code with
standardrb --fix before submitting.
The gem is available as open source under the terms of the MIT License.