diff --git a/lib/active_hash/conditions.rb b/lib/active_hash/conditions.rb index ebbd755..9b91983 100644 --- a/lib/active_hash/conditions.rb +++ b/lib/active_hash/conditions.rb @@ -7,6 +7,11 @@ def initialize(conditions = []) @conditions = conditions end + def initialize_copy(orig) + super + @conditions = @conditions.dup + end + def matches?(record) conditions.all? do |condition| condition.matches?(record) diff --git a/lib/active_hash/relation.rb b/lib/active_hash/relation.rb index b7f5e41..d0debc6 100644 --- a/lib/active_hash/relation.rb +++ b/lib/active_hash/relation.rb @@ -19,7 +19,7 @@ def initialize(klass, all_records, conditions = nil, order_values = nil) end def where(conditions_hash = :chain) - return WhereChain.new(self) if conditions_hash == :chain + return WhereChain.new(spawn) if conditions_hash == :chain spawn.where!(conditions_hash) end @@ -80,7 +80,7 @@ def invert_where! end def spawn - self.class.new(klass, all_records, conditions, order_values) + self.class.new(klass, all_records, conditions.dup, order_values) end def order!(*options) diff --git a/spec/active_hash/base_spec.rb b/spec/active_hash/base_spec.rb index c9420e5..731889e 100644 --- a/spec/active_hash/base_spec.rb +++ b/spec/active_hash/base_spec.rb @@ -497,6 +497,12 @@ class Region < ActiveHash::Base it "filters records for multiple conditions" do expect(Country.where.not(:id => 1, :name => 'Mexico')).to match_array([Country.find(2)]) end + + it "does not mutate the parent relation" do + english = Country.where(language: 'English') + english.where.not(name: 'US') + expect(english.map(&:name)).to match_array(%w[US Canada]) + end end describe ".find_by" do @@ -574,6 +580,14 @@ class Region < ActiveHash::Base it "doesn't finds nil records when searching for ''" do expect(Country.find_by(:language => '')).to be_nil end + + it "does not mutate the relation when called multiple times" do + countries = Country.all + expect(countries.find_by(id: 1).name).to eq("US") + expect(countries.find_by(id: 2).name).to eq("Canada") + expect(countries.find_by(id: 1).name).to eq("US") + expect(countries.length).to eq(4) + end end describe ".find_by!" do