From be8a0c33112fe47e6c28ad41a592a6d9d31d725b Mon Sep 17 00:00:00 2001 From: degwinthegreat Date: Wed, 8 Jul 2026 10:52:07 +0900 Subject: [PATCH 1/2] Fix Relation#load to return self instead of an Array ActiveRecord::Relation#load is expected to return the relation itself, but the bitemporal override ended with `records.each`, whose return value (the records Array) leaked out when valid_datetime or transaction_datetime is set, e.g. `Employee.valid_at(time).load`. Co-Authored-By: Claude Fable 5 --- lib/activerecord-bitemporal/bitemporal.rb | 2 + .../relation/load_spec.rb | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 spec/activerecord-bitemporal/relation/load_spec.rb diff --git a/lib/activerecord-bitemporal/bitemporal.rb b/lib/activerecord-bitemporal/bitemporal.rb index 47b6d72c..29536715 100644 --- a/lib/activerecord-bitemporal/bitemporal.rb +++ b/lib/activerecord-bitemporal/bitemporal.rb @@ -204,6 +204,8 @@ def load record.send(:bitemporal_option_storage)[:valid_datetime] = valid_datetime_ if valid_datetime_ record.send(:bitemporal_option_storage)[:transaction_datetime] = transaction_datetime_ if transaction_datetime_ end + + records end # Use original primary_key for Active Record 8.0+ as much as possible diff --git a/spec/activerecord-bitemporal/relation/load_spec.rb b/spec/activerecord-bitemporal/relation/load_spec.rb new file mode 100644 index 00000000..1e50f3e3 --- /dev/null +++ b/spec/activerecord-bitemporal/relation/load_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ActiveRecord::Bitemporal::Relation do + describe "#load" do + let!(:employees) { Employee.create!([{ name: "Jane" }, { name: "Tom" }]) } + + context "on relation" do + it "returns self" do + relation = Employee.all + expect(relation.load).to equal relation + end + end + + context "on loaded relation" do + it "returns self" do + relation = Employee.all.load + expect(relation.load).to equal relation + end + end + + context "with valid_at" do + it "returns self" do + relation = Employee.valid_at(Time.current) + expect(relation.load).to equal relation + end + end + + context "with transaction_at" do + it "returns self" do + relation = Employee.transaction_at(Time.current) + expect(relation.load).to equal relation + end + end + + context "on empty relation" do + it "returns self" do + relation = Employee.where(name: "Not Found").valid_at(Time.current) + expect(relation.load).to equal relation + end + end + end +end From e3835eec07f2931ceb9bbc97640a3413775baa4a Mon Sep 17 00:00:00 2001 From: degwinthegreat Date: Thu, 9 Jul 2026 11:03:39 +0900 Subject: [PATCH 2/2] Rename local variable records to relation in Relation#load The variable holds the relation itself returned by `super` (Relation#load returns self), not an array of records. Renaming it clarifies that #load returns the relation, as suggested in the PR review. Co-Authored-By: Claude Fable 5 --- lib/activerecord-bitemporal/bitemporal.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/activerecord-bitemporal/bitemporal.rb b/lib/activerecord-bitemporal/bitemporal.rb index 29536715..72272c7a 100644 --- a/lib/activerecord-bitemporal/bitemporal.rb +++ b/lib/activerecord-bitemporal/bitemporal.rb @@ -184,9 +184,9 @@ def load return super if loaded? # このタイミングで先読みしているアソシエーションが読み込まれるので時間を固定 - records = ActiveRecord::Bitemporal.with_bitemporal_option(**bitemporal_option) { super } + relation = ActiveRecord::Bitemporal.with_bitemporal_option(**bitemporal_option) { super } - return records if records.empty? + return relation if relation.empty? valid_datetime_ = valid_datetime if ActiveRecord::Bitemporal.valid_datetime.nil? && (bitemporal_value[:with_valid_datetime].nil? || bitemporal_value[:with_valid_datetime] == :default_scope || valid_datetime_.nil?) @@ -198,14 +198,14 @@ def load transaction_datetime_ = nil end - return records if valid_datetime_.nil? && transaction_datetime_.nil? + return relation if valid_datetime_.nil? && transaction_datetime_.nil? - records.each do |record| + relation.each do |record| record.send(:bitemporal_option_storage)[:valid_datetime] = valid_datetime_ if valid_datetime_ record.send(:bitemporal_option_storage)[:transaction_datetime] = transaction_datetime_ if transaction_datetime_ end - records + relation end # Use original primary_key for Active Record 8.0+ as much as possible