Skip to content

Commit 4902a98

Browse files
Resolve model attribute types on schema load
When running tests in parallel, a new database is created for each test worker (via `ActiveRecord::TestDatabases.create_and_load_schema`). Each of these databases use different OID numbers for custom defined types such as enums. If model schemas are loaded before forking -- as done in `railties/lib/rails/testing/maintain_test_schema.rb` when `eager_load` is true -- Rails will hold on to the OID numbers from the original database. Thus each test worker does not recognize the OID numbers when resolving model attribute types. This commit sidesteps the problem by resolving model attribute types on schema load. This does not address the conflicting OID numbers, but each test worker will inherit properly resolved attribute types. Fixes rails#52607.
1 parent ec667e5 commit 4902a98

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

activerecord/lib/active_record/model_schema.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ def load_schema!
595595
columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
596596
@columns_hash = columns_hash.freeze
597597

598+
_default_attributes # Precompute to cache DB-dependent attribute types
599+
598600
super
599601
end
600602

railties/test/application/test_test.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,46 @@ class User < ApplicationRecord
342342
assert_unsuccessful_run "models/user_test.rb", "Unknown enum attribute 'type' for User"
343343
end
344344

345+
test "database-dependent attribute types are resolved when parallel tests are run in eager load context" do
346+
use_postgresql
347+
rails "db:drop", "db:create"
348+
349+
output = rails("generate", "model", "user")
350+
version = output.match(/(\d+)_create_users\.rb/)[1]
351+
352+
app_file "db/schema.rb", <<~RUBY
353+
ActiveRecord::Schema.define(version: #{version}) do
354+
create_enum "user_favorite_color", ["red", "green", "blue"]
355+
356+
create_table :users do |t|
357+
t.enum :favorite_color, enum_type: :user_favorite_color
358+
end
359+
end
360+
RUBY
361+
362+
app_file "config/initializers/enable_eager_load.rb", <<~RUBY
363+
Rails.application.config.eager_load = true
364+
RUBY
365+
366+
app_file "test/models/user_test.rb", <<~RUBY
367+
require "test_helper"
368+
class UserTest < ActiveSupport::TestCase
369+
ENV.delete("PARALLEL_WORKERS")
370+
parallelize threshold: 1, workers: 2
371+
372+
2.times do |i|
373+
test "favorite_color uses database type (worker \#{i})" do
374+
assert_instance_of ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Enum, User.type_for_attribute("favorite_color")
375+
end
376+
end
377+
end
378+
RUBY
379+
380+
assert_successful_test_run "models/user_test.rb"
381+
ensure
382+
rails "db:drop" rescue nil
383+
end
384+
345385
private
346386
def assert_unsuccessful_run(name, message)
347387
result = run_test_file(name)

0 commit comments

Comments
 (0)