forked from mongodb/mongoid
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MONGOID-5734 Custom polymorphic types (mongodb#5845)
* first pass at a global resolver registry * tests * fix problem with interpreting nested attribute data * need to register subclasses, too * raise custom exceptions when failing to resolve models * fix specs to implement functional around(:context) * trailing white space
- Loading branch information
Showing
25 changed files
with
787 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
lib/mongoid/association/referenced/with_polymorphic_criteria.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mongoid | ||
module Association | ||
module Referenced | ||
# Implements the `with_polymorphic_criteria` shared behavior. | ||
# | ||
# @api private | ||
module WithPolymorphicCriteria | ||
# If the receiver represents a polymorphic association, applies | ||
# the polymorphic search criteria to the given `criteria` object. | ||
# | ||
# @param [ Mongoid::Criteria ] criteria the criteria to append to | ||
# if receiver is polymorphic. | ||
# @param [ Mongoid::Document ] base the document to use when resolving | ||
# the polymorphic type keys. | ||
# | ||
# @return [ Mongoid::Criteria] the resulting criteria, which may be | ||
# the same as the input. | ||
def with_polymorphic_criterion(criteria, base) | ||
if polymorphic? | ||
# 1. get the resolver for the inverse association | ||
resolver = klass.reflect_on_association(as).resolver | ||
|
||
# 2. look up the list of keys from the resolver, given base | ||
keys = resolver.keys_for(base) | ||
|
||
# 3. use equality if there is just one key, `in` if there are multiple | ||
if keys.many? | ||
criteria.where(type => { :$in => keys }) | ||
else | ||
criteria.where(type => keys.first) | ||
end | ||
else | ||
criteria | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mongoid | ||
module Errors | ||
# Raised when a polymorphic association is queried, but the type of the | ||
# association cannot be resolved. This usually happens when the data in | ||
# the database references a type that no longer exists. | ||
# | ||
# For example, consider the following model: | ||
# | ||
# class Manager | ||
# include Mongoid::Document | ||
# belongs_to :unit, polymorphic: true | ||
# end | ||
# | ||
# Imagine there is a document in the `managers` collection that looks | ||
# something like this: | ||
# | ||
# { _id: ..., unit_id: ..., unit_type: 'Department::Engineering' } | ||
# | ||
# If, at some point in your refactoring, you rename the `Department::Engineering` | ||
# model to something else, Mongoid will no longer be able to resolve the | ||
# type of this association, and asking for `manager.unit` will raise this | ||
# exception. | ||
# | ||
# To fix this exception, you can add an alias to the model class so that it | ||
# can still be found, even after renaming it: | ||
# | ||
# module Engineering | ||
# class Department | ||
# include Mongoid::Document | ||
# | ||
# identify_as 'Department::Engineering' | ||
# | ||
# # ... | ||
# end | ||
# end | ||
# | ||
# Better practice would be to use unique strings instead of class names to | ||
# identify these polymorphic types in the database (e.g. 'dept' instead of | ||
# 'Department::Engineering'). | ||
class UnrecognizedModelAlias < MongoidError | ||
def initialize(model_alias) | ||
super( | ||
compose_message( | ||
'unrecognized_model_alias', | ||
model_alias: model_alias.inspect | ||
) | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
module Mongoid | ||
module Errors | ||
# Raised when a model resolver is referenced, but not registered. | ||
# | ||
# class Manager | ||
# include Mongoid::Document | ||
# belongs_to :unit, polymorphic: :org | ||
# end | ||
# | ||
# If `:org` has not previously been registered as a model resolver, | ||
# Mongoid will raise UnrecognizedResolver when it tries to resolve | ||
# a manager's unit. | ||
class UnrecognizedResolver < MongoidError | ||
def initialize(resolver) | ||
super( | ||
compose_message( | ||
'unrecognized_resolver', | ||
resolver: resolver.inspect, | ||
resolvers: [ :default, *Mongoid::ModelResolver.resolvers.keys ].inspect | ||
) | ||
) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.