From ca40a586e77c18320a49d9dae1d42e495e4f1d19 Mon Sep 17 00:00:00 2001 From: Mattias Pfeiffer Date: Tue, 4 Oct 2022 12:43:50 +0200 Subject: [PATCH] Relation: Make `where` return a fresh relation to avoid leaking scopes --- lib/active_hash/relation.rb | 19 ++++++++----------- spec/active_hash/base_spec.rb | 8 ++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/active_hash/relation.rb b/lib/active_hash/relation.rb index 90a7b50f..4de5b6ba 100644 --- a/lib/active_hash/relation.rb +++ b/lib/active_hash/relation.rb @@ -11,16 +11,14 @@ def initialize(klass, all_records, query_hash = nil) self.klass = klass self.all_records = all_records self.query_hash = query_hash - self.records_dirty = false - self end def where(query_hash = :chain) - return ActiveHash::Base::WhereChain.new(self) if query_hash == :chain - - self.records_dirty = true unless query_hash.nil? || query_hash.keys.empty? - self.query_hash.merge!(query_hash || {}) - self + if query_hash == :chain + ActiveHash::Base::WhereChain.new(self) + else + self.class.new(klass, all_records, self.query_hash.merge(query_hash || {})) + end end def all(options = {}) @@ -111,14 +109,14 @@ def method_missing(method_name, *args) instance_exec(*args, &self.klass.scopes[method_name]) end - attr_reader :query_hash, :klass, :all_records, :records_dirty + attr_reader :query_hash, :klass, :all_records private - attr_writer :query_hash, :klass, :all_records, :records_dirty + attr_writer :query_hash, :klass, :all_records def records - if !defined?(@records) || @records.nil? || records_dirty + if !defined?(@records) || @records.nil? reload else @records @@ -126,7 +124,6 @@ def records end def filter_all_records_by_query_hash - self.records_dirty = false return all_records if query_hash.blank? # use index if searching by id diff --git a/spec/active_hash/base_spec.rb b/spec/active_hash/base_spec.rb index 4c6b5063..20ef8dcf 100644 --- a/spec/active_hash/base_spec.rb +++ b/spec/active_hash/base_spec.rb @@ -236,6 +236,14 @@ class Region < ActiveHash::Base Country.where(:language => 'English').all? { |country| expect(country).to be_kind_of(Country) } end + it "doesn't affect the original" do + countries = Country.where(:language => 'English') + + expect(countries.size).to eq 2 + expect(countries.where(name: "US").size).to eq 1 + expect(countries.size).to eq 2 + end + it "populates the data correctly" do records = Country.where(:language => 'English') expect(records.first.id).to eq(1)