From 7cea3543428aef1309dd1fea960386b952e74812 Mon Sep 17 00:00:00 2001 From: Yasuo Honda Date: Tue, 14 Apr 2026 09:39:39 +0900 Subject: [PATCH] Prefer ActiveRecord.default_timezone over per-class accessor (#234) Calling `ar_class.default_timezone` on Rails 7.0.x prints DEPRECATION WARNING: ActiveRecord::Base.default_timezone is deprecated and will be removed in Rails 7.1. Use ActiveRecord.default_timezone instead. even though both accessors return the same value. The per-class accessor was introduced as a deprecated proxy in Rails 7.0 (rails/rails@c3f43075a3) and removed entirely in Rails 7.1 (rails/rails@96c9db1b48), so the warning only fires on Rails 7.0.x. Switch the order in PLSQL::Schema#default_timezone so that we ask the module-level ActiveRecord.default_timezone first when it is available (AR 7.0+) and only fall back to the per-class accessor on pre-7.0 AR where the module-level one does not exist. This silences the warning on Rails 7.0.x and is a no-op on Rails 7.1+ (where the per-class accessor was already gone) and on Rails <= 6.x (where the module-level accessor did not yet exist). Add a regression test that captures deprecator output while resolving plsql.default_timezone with `activerecord_class` set, and asserts that no warning mentioning default_timezone was raised. The existing ActiveRecord.default_timezone is captured before assignment and restored from the ensure block alongside the deprecator behavior so the test is order-independent. Verified by #269 / #271 that the test fails on AR 7.0 without this fix and passes on AR 7.1+ regardless. Fixes #234 References: - rails/rails@c3f43075a3 (added the deprecated delegators in Rails 7.0) - rails/rails@96c9db1b48 (removed them in Rails 7.1) Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/plsql/schema.rb | 15 +++++++++------ spec/plsql/schema_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/lib/plsql/schema.rb b/lib/plsql/schema.rb index 165811a0..2062bef5 100644 --- a/lib/plsql/schema.rb +++ b/lib/plsql/schema.rb @@ -99,12 +99,15 @@ def default_timezone @original_schema.default_timezone else @default_timezone || - # Use ActiveRecord default_timezone when ActiveRecord connection is used, - # preferring the connection's activerecord_class so a subclass override - # (available in AR < 8.0) is honored before falling back to the - # module-level accessor (AR 7.0+; the only one in AR 8.0+). - (@connection && (ar_class = @connection.activerecord_class) && - (ar_class.respond_to?(:default_timezone) ? ar_class.default_timezone : ActiveRecord.default_timezone)) || + # Use ActiveRecord default_timezone when ActiveRecord connection is used. + # Prefer the module-level accessor (AR 7.0+; the only one in AR 8.0+) so + # that AR 7.0/7.1's deprecation warning for ActiveRecord::Base.default_timezone + # is not emitted. Fall back to the per-class accessor only on pre-7.0 AR, + # where ActiveRecord.default_timezone does not exist. + (@connection && @connection.activerecord_class && + (ActiveRecord.respond_to?(:default_timezone) ? + ActiveRecord.default_timezone : + @connection.activerecord_class.default_timezone)) || # default to local timezone :local end diff --git a/spec/plsql/schema_spec.rb b/spec/plsql/schema_spec.rb index 0662882b..d540e3ea 100644 --- a/spec/plsql/schema_spec.rb +++ b/spec/plsql/schema_spec.rb @@ -218,6 +218,26 @@ class TestModel < TestBaseModel expect(plsql.default_timezone).to eq(:utc) end + it "should not emit ActiveRecord::Base.default_timezone deprecation warning (#234)" do + skip "ActiveRecord.default_timezone is not available" unless ActiveRecord.respond_to?(:default_timezone=) + + original_default_timezone = ActiveRecord.default_timezone + ActiveRecord.default_timezone = :utc + + deprecator = ActiveRecord.respond_to?(:deprecator) ? ActiveRecord.deprecator : ActiveSupport::Deprecation + original_behavior = deprecator.behavior + warnings = [] + begin + deprecator.behavior = ->(message, *) { warnings << message } + expect(plsql.default_timezone).to eq(:utc) + ensure + deprecator.behavior = original_behavior + ActiveRecord.default_timezone = original_default_timezone + end + + expect(warnings.grep(/default_timezone/)).to be_empty + end + it "should have the same connection as default schema" do expect(plsql.hr.connection).to eq(plsql.connection) end