diff --git a/CHANGELOG.md b/CHANGELOG.md index e288665de8..ac1be3c740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,8 @@ For instructions on upgrading to newer versions, visit ### Resolved Issues +* \#1680 Polymorphic relations now use `*_type` keys in lookup queries. + * \#1676 Allow eager loading to work as a default scope. * \#1665/#1672 Expand complex criteria in nested criteria selectors, like diff --git a/lib/mongoid/relations/builders/referenced/many.rb b/lib/mongoid/relations/builders/referenced/many.rb index 7aacfa6693..511ecbbba9 100644 --- a/lib/mongoid/relations/builders/referenced/many.rb +++ b/lib/mongoid/relations/builders/referenced/many.rb @@ -17,7 +17,7 @@ class Many < Builder def build(type = nil) return object unless query? return [] if object.is_a?(Array) - crit = metadata.criteria(Conversions.flag(object, metadata)) + crit = metadata.criteria(Conversions.flag(object, metadata), base.class) IdentityMap.get(crit.klass, crit.selector) || crit end end diff --git a/lib/mongoid/relations/builders/referenced/many_to_many.rb b/lib/mongoid/relations/builders/referenced/many_to_many.rb index 784a355045..1034c94fdf 100644 --- a/lib/mongoid/relations/builders/referenced/many_to_many.rb +++ b/lib/mongoid/relations/builders/referenced/many_to_many.rb @@ -17,7 +17,7 @@ class ManyToMany < Builder def build(type = nil) return object.try(:dup) unless query? ids = object || [] - crit = metadata.criteria(ids) + crit = metadata.criteria(ids, base.class) IdentityMap.get(crit.klass, ids) || crit end diff --git a/lib/mongoid/relations/builders/referenced/one.rb b/lib/mongoid/relations/builders/referenced/one.rb index 8139908888..8c57ee9f8d 100644 --- a/lib/mongoid/relations/builders/referenced/one.rb +++ b/lib/mongoid/relations/builders/referenced/one.rb @@ -17,7 +17,7 @@ class One < Builder def build(type = nil) return object unless query? return nil if base.new_record? - metadata.criteria(Conversions.flag(object, metadata)).from_map_or_db + metadata.criteria(Conversions.flag(object, metadata), base.class).from_map_or_db end end end diff --git a/lib/mongoid/relations/metadata.rb b/lib/mongoid/relations/metadata.rb index 3b2ef212ae..88c9ca14c4 100644 --- a/lib/mongoid/relations/metadata.rb +++ b/lib/mongoid/relations/metadata.rb @@ -135,11 +135,12 @@ def constraint # metadata.criteria([ id_one, id_two ]) # # @param [ Object ] object The foreign key used for the query. + # @param [ Class ] type The base class. # # @return [ Criteria ] The criteria. # # @since 2.1.0 - def criteria(object, type = nil) + def criteria(object, type) query = relation.criteria(self, object, type) order ? query.order_by(order) : query end diff --git a/lib/mongoid/relations/referenced/many.rb b/lib/mongoid/relations/referenced/many.rb index 22209751b9..d9d3b02671 100644 --- a/lib/mongoid/relations/referenced/many.rb +++ b/lib/mongoid/relations/referenced/many.rb @@ -389,7 +389,7 @@ def collection # # @since 2.0.0.beta.1 def criteria - Many.criteria(metadata, Conversions.flag(base.id, metadata)) + Many.criteria(metadata, Conversions.flag(base.id, metadata), base.class) end # Perform the necessary cascade operations for documents that just got @@ -536,7 +536,11 @@ def builder(base, meta, object) # # @since 2.1.0 def criteria(metadata, object, type = nil) - metadata.klass.where(metadata.foreign_key => object) + crit = metadata.klass.where(metadata.foreign_key => object) + if metadata.polymorphic? + crit = crit.where(metadata.type => type.name) + end + crit end # Eager load the relation based on the criteria. diff --git a/lib/mongoid/relations/referenced/one.rb b/lib/mongoid/relations/referenced/one.rb index 369640d32d..3373f18cb2 100644 --- a/lib/mongoid/relations/referenced/one.rb +++ b/lib/mongoid/relations/referenced/one.rb @@ -122,7 +122,11 @@ def builder(base, meta, object) # # @since 2.1.0 def criteria(metadata, object, type = nil) - metadata.klass.where(metadata.foreign_key => object) + crit = metadata.klass.where(metadata.foreign_key => object) + if metadata.polymorphic? + crit = crit.where(metadata.type => type.name) + end + crit end # Get the criteria that is used to eager load a relation of this diff --git a/lib/mongoid/relations/synchronization.rb b/lib/mongoid/relations/synchronization.rb index 90667d1db0..d2947c0247 100644 --- a/lib/mongoid/relations/synchronization.rb +++ b/lib/mongoid/relations/synchronization.rb @@ -61,7 +61,7 @@ def synced?(foreign_key) # # @since 2.2.1 def remove_inverse_keys(meta) - meta.criteria(send(meta.foreign_key)).pull(meta.inverse_foreign_key, id) + meta.criteria(send(meta.foreign_key), self.class).pull(meta.inverse_foreign_key, id) end # Update the inverse keys for the relation. @@ -91,10 +91,10 @@ def update_inverse_keys(meta) end unless adds.empty? - meta.criteria(adds).add_to_set(meta.inverse_foreign_key, id) + meta.criteria(adds, self.class).add_to_set(meta.inverse_foreign_key, id) end unless subs.empty? - meta.criteria(subs).pull(meta.inverse_foreign_key, id) + meta.criteria(subs, self.class).pull(meta.inverse_foreign_key, id) end end end diff --git a/spec/mongoid/relations/referenced/many_spec.rb b/spec/mongoid/relations/referenced/many_spec.rb index b8e3c4be8c..7ca874c444 100644 --- a/spec/mongoid/relations/referenced/many_spec.rb +++ b/spec/mongoid/relations/referenced/many_spec.rb @@ -1598,6 +1598,45 @@ end end + describe ".criteria" do + + let(:id) do + BSON::ObjectId.new + end + + context "when the relation is polymorphic" do + + let(:metadata) do + Movie.relations["ratings"] + end + + let(:criteria) do + described_class.criteria(metadata, id, Movie) + end + + it "includes the type in the criteria" do + criteria.selector.should eq( + { "ratable_id" => id, "ratable_type" => "Movie" } + ) + end + end + + context "when the relation is not polymorphic" do + + let(:metadata) do + Person.relations["posts"] + end + + let(:criteria) do + described_class.criteria(metadata, id, Person) + end + + it "does not include the type in the criteria" do + criteria.selector.should eq({ "person_id" => id }) + end + end + end + describe "#delete" do let!(:person) do diff --git a/spec/mongoid/relations/referenced/one_spec.rb b/spec/mongoid/relations/referenced/one_spec.rb index fc615cdf2f..6952fc3ba6 100644 --- a/spec/mongoid/relations/referenced/one_spec.rb +++ b/spec/mongoid/relations/referenced/one_spec.rb @@ -958,6 +958,45 @@ end end + describe ".criteria" do + + let(:id) do + BSON::ObjectId.new + end + + context "when the relation is polymorphic" do + + let(:metadata) do + Book.relations["rating"] + end + + let(:criteria) do + described_class.criteria(metadata, id, Book) + end + + it "includes the type in the criteria" do + criteria.selector.should eq( + { "ratable_id" => id, "ratable_type" => "Book" } + ) + end + end + + context "when the relation is not polymorphic" do + + let(:metadata) do + Person.relations["game"] + end + + let(:criteria) do + described_class.criteria(metadata, id, Person) + end + + it "does not include the type in the criteria" do + criteria.selector.should eq({ "person_id" => id }) + end + end + end + describe ".eager_load" do before do