Skip to content

Commit

Permalink
Polymorphic relations now use _type fields in their queries. Fixes #1…
Browse files Browse the repository at this point in the history
…680.
  • Loading branch information
durran committed Feb 6, 2012
1 parent 3a1e88a commit 2f94b5f
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/relations/builders/referenced/many.rb
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/relations/builders/referenced/many_to_many.rb
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/relations/builders/referenced/one.rb
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion lib/mongoid/relations/metadata.rb
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions lib/mongoid/relations/referenced/many.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion lib/mongoid/relations/referenced/one.rb
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions lib/mongoid/relations/synchronization.rb
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions spec/mongoid/relations/referenced/many_spec.rb
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions spec/mongoid/relations/referenced/one_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit 2f94b5f

Please sign in to comment.