Hello all,
I'm struggling to understand why an `after_create_commit` is executed in an example although `use_transactional_fixtures` is set to `true`.
I created a new Rails app to isolate/test this behavior:
ruby 3.1.2
rails 7.0.4.3
rspec-rails 6.0.1
$ rails g scaffold article title content:text
$ rails g scaffold comment article:references content:text
Here are the models:
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
after_create_commit -> { comments.create!(content: "First comment of #{title}") }
end
class Comment < ApplicationRecord
belongs_to :article
end
Then I wrote the following test:
require 'rails_helper'
RSpec.describe Article, type: :model do
describe "create" do
subject { described_class.create!(title: "Hello", content: "world") }
it 'does not create a first comment' do
ActiveRecord::Base.logger = Logger.new(STDOUT)
expect { subject }.not_to change(Comment, :count).by(1)
end
end
end
I expect it NOT to create a comment because, from my understanding:
- The example is run within a transaction
- The after_create_commit is supposed to be run only after the transaction is committed
- RSpec is supposed to rollback the transaction (once the example is over) instead of committing it
- No commit, no after_create_commit. No after_create_commit, not comment created.
To my surprise, the comment _is_ created. Here is the SQL log for the above example:
```sql
D, [2023-04-26T15:51:25.707540 #346392] DEBUG -- : Comment Count (0.0ms) SELECT COUNT(*) FROM "comments"
D, [2023-04-26T15:51:25.709992 #346392] DEBUG -- : TRANSACTION (0.0ms) SAVEPOINT active_record_1
D, [2023-04-26T15:51:25.710339 #346392] DEBUG -- : Article Create (0.1ms) INSERT INTO "articles" ("title", "content", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "Hello"], ["content", "world"], ["created_at", "2023-04-26 13:51:25.709772"], ["updated_at", "2023-04-26 13:51:25.709772"]]
D, [2023-04-26T15:51:25.710480 #346392] DEBUG -- : TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1
D, [2023-04-26T15:51:25.713710 #346392] DEBUG -- : TRANSACTION (0.0ms) SAVEPOINT active_record_1
D, [2023-04-26T15:51:25.713915 #346392] DEBUG -- : Comment Create (0.0ms) INSERT INTO "comments" ("article_id", "content", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["article_id", 1], ["content", "First comment of Hello"], ["created_at", "2023-04-26 13:51:25.713563"], ["updated_at", "2023-04-26 13:51:25.713563"]]
D, [2023-04-26T15:51:25.714024 #346392] DEBUG -- : TRANSACTION (0.0ms) RELEASE SAVEPOINT active_record_1
D, [2023-04-26T15:51:25.714173 #346392] DEBUG -- : Comment Count (0.0ms) SELECT COUNT(*) FROM "comments"
D, [2023-04-26T15:51:25.725359 #346392] DEBUG -- : TRANSACTION (0.1ms) rollback transaction
```
It seems that the after_create_commit block is run after the savepoint, which does not have the same meaning in my mind as after a commit. A savepoint can still be rolled back so I'm not yet sure the data is effectively persisted in the database while a commit cannot be rolled back and the data _is_ persisted.
Am I missing something here? Any explanation/help will be much appreciated!
Thanks