Skip to content

Commit 570dbdb

Browse files
committed
Add Ensure Record Saved With after_commit Callback as a Rails TIL
1 parent b3a6c52 commit 570dbdb

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
1010

1111
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
1212

13-
_1316 TILs and counting..._
13+
_1317 TILs and counting..._
1414

1515
---
1616

@@ -807,6 +807,7 @@ _1316 TILs and counting..._
807807
- [Disambiguate Where In A Joined Relation](rails/disambiguate-where-in-a-joined-relation.md)
808808
- [Ensure A Rake Task Cannot Write Data](rails/ensure-a-rake-task-cannot-write-data.md)
809809
- [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md)
810+
- [Ensure Record Saved With after_commit Callback](rails/ensure-record-saved-with-after-commit-callback.md)
810811
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
811812
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
812813
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Ensure Record Saved With after_commit Callback
2+
3+
In my experience, some of the more common `ActiveRecord` callbacks are ones
4+
like `before_save` or `after_update`. While working with some code, where I
5+
needed to send a notification when a certain value was updated, I learned that
6+
something like `after_update` wasn't sufficient.
7+
8+
If my record is updated within a transaction, the `after_update` will get
9+
triggered even though the changes could later get rolled back resulting in me
10+
erroneously sending the notification.
11+
12+
```ruby
13+
ActiveRecord::Base.transaction do
14+
user.update(interesting_value: 123)
15+
16+
do_something # <-- rollback could happen here!
17+
end
18+
```
19+
20+
To ensure I'm not over-eager with my notifications, I should instead use
21+
[`after_commit`](https://api.rubyonrails.org/v7.0.5/classes/ActiveRecord/Transactions/ClassMethods.html#method-i-after_commit)
22+
which only gets called after the changes have been committed to the database.
23+
24+
```ruby
25+
class User < ApplicationRecord
26+
after_commit :send_notification,
27+
on: [:create, :update],
28+
if: :interesting_value_was_changed?
29+
30+
# rest of class...
31+
32+
private
33+
34+
def send_notification
35+
# logic...
36+
end
37+
38+
def interesting_value_was_changed?
39+
# logic...
40+
end
41+
end
42+
```
43+
44+
On either `create` or `update` if my condition is met, then after the _commit_
45+
goes through, the `#send_notification` method will be triggered.

0 commit comments

Comments
 (0)