with_model
with_model copied to clipboard
Error when used on MySQL with transactional_fixtures enabled in RSpec
When Rails application is tested with RSpec and transactional_fixtures are enabled:
RSpec.configure do |config|
config.extend WithModel
config.use_transactional_fixtures = true
end
RSpec.describe "TestModel" do
with_model :TestModel do
table do |t|
t.string :title
end
end
it "works" do
expect(TestModel.create!(title: "Whatever")).to be_present
end
end
Following error is thrown when a with_model record is created:
SAVEPOINT active_record_1 does not exist
Test logs:
TRANSACTION (0.1ms) BEGIN
(21.5ms) CREATE TABLE `with_model_test_models_178402_9300` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `title` varchar(255))
TRANSACTION (0.3ms) SAVEPOINT active_record_1
TestModel Create (2.0ms) INSERT INTO `with_model_test_models_178402_9300` (`title`) VALUES ('Whatever')
TRANSACTION (0.3ms) RELEASE SAVEPOINT active_record_1
TRANSACTION (0.1ms) ROLLBACK TO SAVEPOINT active_record_1
(4.2ms) DROP TABLE `with_model_test_models_178402_9300`
Note that ROLLBACK TO SAVEPOINT active_record_1 used after releasing that same savepoint instead of just ROLLBACK of the whole transaction.
Correct logs from PostgreSQL example
TRANSACTION (0.2ms) BEGIN
(3.4ms) CREATE TABLE "with_model_test_models_182673_6320" ("id" bigserial primary key, "title" character varying)
TRANSACTION (0.5ms) SAVEPOINT active_record_1
TestModel Create (1.2ms) INSERT INTO "with_model_test_models_182673_6320" ("title") VALUES ($1) RETURNING "id" [["title", "Whatever"]]
TRANSACTION (0.4ms) RELEASE SAVEPOINT active_record_1
(0.8ms) DROP TABLE "with_model_test_models_182673_6320"
TRANSACTION (0.4ms) ROLLBACK
Environment:
Gem version: 2.2.0 Rails version: 7.2 and 8.0, both mysql2 and trilogy adapters.
Reproduction steps:
-
Run MySQL server. E.g. with Docker:
docker run --rm -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -e MYSQL_DATABASE=test -p 3306:3306 mysql:latest -
Run reproduction executable test case: https://gist.github.com/Envek/1e152e913787554379ec2834cdeaf169
wget https://gist.github.com/Envek/1e152e913787554379ec2834cdeaf169/raw/09e2bc0a4501322842e5462fdb222d7475ea551e/with_model_mysql_spec.rb ruby with_model_mysql_spec.rb
Workaround:
Replace with_model with manual table and model creation.
Manual table and model creation.
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
ActiveRecord::Schema.define do
drop_table :dynamodb_attrs, if_exists: true
create_table :test_models do |t|
t.string :title
end
end
end
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
ActiveRecord::Schema.define do
drop_table :test_models, if_exists: true
end
end
# Stub the constant for each example
before do
stub_const("TestModel", Class.new(ActiveRecord::Base) do
self.table_name = "test_models"
end)
end