From cc1da5b697dcd248196bf7beea7733c879d5ae46 Mon Sep 17 00:00:00 2001 From: Alex Vondrak Date: Tue, 6 May 2025 14:56:42 -0400 Subject: [PATCH] Support Rails 7.2 --- Gemfile.lock | 42 +++++++++++++----------- activerecord-delay_touching.gemspec | 2 +- spec/activerecord/delay_touching_spec.rb | 42 +++++++++++++++++------- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5e8aefa..88302e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,41 +2,43 @@ PATH remote: . specs: activerecord-delay_touching (1.1.2) - activerecord (>= 4.2, < 7.2) + activerecord (>= 4.2, < 7.3) GEM remote: https://rubygems.org/ specs: - activemodel (7.1.3) - activesupport (= 7.1.3) - activerecord (7.1.3) - activemodel (= 7.1.3) - activesupport (= 7.1.3) + activemodel (7.2.2.1) + activesupport (= 7.2.2.1) + activerecord (7.2.2.1) + activemodel (= 7.2.2.1) + activesupport (= 7.2.2.1) timeout (>= 0.4.0) - activesupport (7.1.3) + activesupport (7.2.2.1) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) base64 (0.2.0) - bigdecimal (3.1.5) + benchmark (0.4.0) + bigdecimal (3.1.9) builder (3.2.4) - concurrent-ruby (1.2.2) - connection_pool (2.4.1) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) diff-lcs (1.5.0) docile (1.4.0) - drb (2.2.0) - ruby2_keywords - i18n (1.12.0) + drb (2.2.1) + i18n (1.14.7) concurrent-ruby (~> 1.0) + logger (1.7.0) mini_portile2 (2.8.1) - minitest (5.18.0) - mutex_m (0.2.0) + minitest (5.25.5) rack (2.2.6.3) rake (13.0.6) rspec (3.12.0) @@ -55,7 +57,7 @@ GEM rack (>= 1.0.0) rspec (>= 1.3.0) rspec-support (3.12.0) - ruby2_keywords (0.0.5) + securerandom (0.4.1) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) @@ -67,7 +69,7 @@ GEM sqlite3 (1.6.1) mini_portile2 (~> 2.8.0) timecop (0.9.6) - timeout (0.4.1) + timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) yarjuf (2.0.0) diff --git a/activerecord-delay_touching.gemspec b/activerecord-delay_touching.gemspec index 42d5025..0016646 100644 --- a/activerecord-delay_touching.gemspec +++ b/activerecord-delay_touching.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.add_dependency "activerecord", ">= 4.2", "< 7.2" + spec.add_dependency "activerecord", ">= 4.2", "< 7.3" end diff --git a/spec/activerecord/delay_touching_spec.rb b/spec/activerecord/delay_touching_spec.rb index f200c68..4abec2d 100644 --- a/spec/activerecord/delay_touching_spec.rb +++ b/spec/activerecord/delay_touching_spec.rb @@ -5,6 +5,17 @@ let(:pet1) { Pet.create(name: "Bones") } let(:pet2) { Pet.create(name: "Ema") } + + # Rails 7.2 deprecated ActiveRecord::Base.connection in favor of .lease_connection and .with_connection. By default, + # rspec should already have established an active connection around each test which gets reused by each downstream + # call to .lease_connection & .with_connection within ActiveRecord. However, Base.lease_connection doesn't make it + # clear that the same connection is reused, so we codify this expectation a little more explicitly by using this + # `let!`, which is eagerly evaluated for each test and gives us a value to use for assertions. + let!(:connection) do + expect(ActiveRecord::Base.connection_pool.active_connection?).to be_truthy, "rspec isn't connected to the db" + ActiveRecord::Base.connection_pool.active_connection + end + it 'has a version number' do expect(Activerecord::DelayTouching::VERSION).not_to be nil end @@ -126,24 +137,31 @@ end it 'will not connect to the database if there are no touches' do - expect(ActiveRecord::Base).not_to receive(:connection) - ActiveRecord::Base.delay_touching do - # no touches, so no reason to fetch a connection + expect(ActiveRecord::Base).not_to receive(:lease_connection) + expect(ActiveRecord::Base).not_to receive(:with_connection) + expect_updates [] do + ActiveRecord::Base.delay_touching do + # no touches, so no reason to fetch a connection + end end end it 'will not connect to the database if none of the touches are persisted' do - expect(ActiveRecord::Base).not_to receive(:connection) - ActiveRecord::Base.delay_touching do - Pet.new.touch # not persisted, so won't cause updates + expect(ActiveRecord::Base).not_to receive(:lease_connection) + expect(ActiveRecord::Base).not_to receive(:with_connection) + expect_updates [] do + ActiveRecord::Base.delay_touching do + Pet.new.touch # not persisted, so won't cause updates + end end end it 'still connects to the database for other queries, even if there are no touches' do - expect(ActiveRecord::Base.connection).not_to receive(:update) # no touches - expect(ActiveRecord::Base).to receive(:connection).at_least(:once).and_call_original - ActiveRecord::Base.delay_touching do - expect(Pet.count).to be >= 0 # query should still work + expect(ActiveRecord::Base).to receive(:with_connection).at_least(:once).and_call_original + expect_updates [] do + ActiveRecord::Base.delay_touching do + expect(Pet.count).to be >= 0 # query should still work + end end end @@ -199,7 +217,7 @@ it 'does not infinitely loop' do updates = 0 - allow(ActiveRecord::Base.connection).to receive(:update).and_wrap_original do |m, *args| + allow(connection).to receive(:update).and_wrap_original do |m, *args| updates = updates + 1 raise StandardError, 'Too many updates - likely infinite loop detected' if updates > 1 @@ -229,7 +247,7 @@ def expect_updates(tables) Regexp.new(%Q{UPDATE "#{entry}" SET "updated_at" = }) end end.flatten - expect(ActiveRecord::Base.connection).to receive(:update).exactly(expected_sql.length).times do |stmt, _, _| + expect(connection).to receive(:update).exactly(expected_sql.length).times do |stmt, _, _| index = expected_sql.index { |sql| stmt.to_sql =~ sql} expect(index).to be, "An unexpected touch occurred: #{stmt.to_sql}" expected_sql.delete_at(index)