mongoid 9.0.1 → 9.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/config/locales/en.yml +16 -0
- data/lib/mongoid/association/accessors.rb +7 -2
- data/lib/mongoid/association/nested/one.rb +14 -1
- data/lib/mongoid/association/referenced/belongs_to/binding.rb +7 -1
- data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
- data/lib/mongoid/association/referenced/belongs_to.rb +15 -0
- data/lib/mongoid/association/referenced/has_many.rb +9 -8
- data/lib/mongoid/association/referenced/has_one/buildable.rb +3 -8
- data/lib/mongoid/association/referenced/with_polymorphic_criteria.rb +41 -0
- data/lib/mongoid/attributes/nested.rb +2 -1
- data/lib/mongoid/clients/sessions.rb +12 -15
- data/lib/mongoid/composable.rb +2 -0
- data/lib/mongoid/document.rb +2 -0
- data/lib/mongoid/errors/unrecognized_model_alias.rb +53 -0
- data/lib/mongoid/errors/unrecognized_resolver.rb +27 -0
- data/lib/mongoid/errors/unregistered_class.rb +47 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/identifiable.rb +28 -0
- data/lib/mongoid/model_resolver.rb +154 -0
- data/lib/mongoid/persistence_context.rb +2 -1
- data/lib/mongoid/traversable.rb +5 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/associations/belongs_to_spec.rb +129 -0
- data/spec/integration/persistence/collection_options_spec.rb +36 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +4 -0
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +1 -0
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +58 -21
- data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +4 -0
- data/spec/mongoid/attributes/nested_spec.rb +1 -0
- data/spec/mongoid/clients/transactions_spec.rb +2 -2
- data/spec/mongoid/model_resolver_spec.rb +167 -0
- data/spec/mongoid/monkey_patches_spec.rb +1 -1
- data/spec/mongoid/persistence_context_spec.rb +17 -4
- data/spec/mongoid/serializable_spec.rb +16 -9
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 558b30b0a39cd36cd9a3e54695f4617a9fcc0d67300637d1299b487b7d911bda
|
4
|
+
data.tar.gz: eccf9c55bdde17fd38592427e0dd6b5545d3e605b94a4308a422ba332e20c183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 420ac9d23abeecb04c19794df124fc80d4f99883e1156d4e3be42e79b4b2e5e5a558c6b650746784024f0477a800def3a2ded537b848d3e9b97fb5e5e220b1f0
|
7
|
+
data.tar.gz: 40bfdcaf862e3ae7d3d046d84d5f9f5eea4752b5559c869eda16e1bd00cbc9aaae3eef05a7e4bec497915619fb162a248ac8f4be3525068e81f28ae876af1a29
|
data/lib/config/locales/en.yml
CHANGED
@@ -680,6 +680,22 @@ en:
|
|
680
680
|
resolution: "The _type field is a reserved one used by Mongoid to determine the
|
681
681
|
class for instantiating an object. Please don't save data in this field or ensure
|
682
682
|
that any values in this field correspond to valid models."
|
683
|
+
unrecognized_model_alias:
|
684
|
+
message: "Cannot find any model with type %{model_alias}"
|
685
|
+
summary: "A document is trying to load a polymorphic association, but the data refers to a type of object that can't be resolved (%{model_alias}). It might be that you've renamed the target class."
|
686
|
+
resolution: "Register the old name as an alias on the refactored target object, using `identify_as`. This will allow Mongoid to find the target type even if the name no longer matches what was stored in the database."
|
687
|
+
unrecognized_resolver:
|
688
|
+
message: "The model resolver %{resolver} was referenced, but never registered."
|
689
|
+
summary: "A polymorphic association has been configured to use a resolver
|
690
|
+
named %{resolver}, but that resolver has not yet been registered. This
|
691
|
+
might be a typo. Currently registered resolvers are: %{resolvers}."
|
692
|
+
resolution: "Register custom resolvers with
|
693
|
+
`Mongoid::ModelResolver.register_resolver` before attempting to query
|
694
|
+
a polymorphic association."
|
695
|
+
unregistered_class:
|
696
|
+
message: "The class %{klass} is not registered with the resolver %{resolver}."
|
697
|
+
summary: "A polymorphic association using the resolver %{resolver} has tried to link to a model of type %{klass}, but the resolver has no knowledge of any such model. This can happen if the association is configured to use a different resolver than the target mode."
|
698
|
+
resolution: "Make sure the target model is registered with the same resolver as the polymorphic association, using `identify_as`."
|
683
699
|
unsaved_document:
|
684
700
|
message: "Attempted to save %{document} before the parent %{base}."
|
685
701
|
summary: "You cannot call create or create! through the
|
@@ -42,7 +42,8 @@ module Mongoid
|
|
42
42
|
#
|
43
43
|
# @return [ Proxy ] The association.
|
44
44
|
def create_relation(object, association, selected_fields = nil)
|
45
|
-
|
45
|
+
key = @attributes[association.inverse_type]
|
46
|
+
type = key ? association.resolver.model_for(key) : nil
|
46
47
|
target = if t = association.build(self, object, type, selected_fields)
|
47
48
|
association.create_relation(self, t)
|
48
49
|
else
|
@@ -116,7 +117,11 @@ module Mongoid
|
|
116
117
|
# during binding or when cascading callbacks. Whenever we retrieve
|
117
118
|
# associations within the codebase, we use without_autobuild.
|
118
119
|
if !without_autobuild? && association.embedded? && attribute_missing?(field_name)
|
119
|
-
|
120
|
+
# We always allow accessing the parent document of an embedded one.
|
121
|
+
try_get_parent = association.is_a?(
|
122
|
+
Mongoid::Association::Embedded::EmbeddedIn
|
123
|
+
) && field_name == association.key
|
124
|
+
raise Mongoid::Errors::AttributeNotLoaded.new(self.class, field_name) unless try_get_parent
|
120
125
|
end
|
121
126
|
|
122
127
|
if !reload && (value = ivar(name)) != false
|
@@ -53,12 +53,25 @@ module Mongoid
|
|
53
53
|
@attributes = attributes.with_indifferent_access
|
54
54
|
@association = association
|
55
55
|
@options = options
|
56
|
-
@class_name = options[:class_name]
|
56
|
+
@class_name = class_from(options[:class_name])
|
57
57
|
@destroy = @attributes.delete(:_destroy)
|
58
58
|
end
|
59
59
|
|
60
60
|
private
|
61
61
|
|
62
|
+
# Coerces the argument into a class, or defaults to the association's class.
|
63
|
+
#
|
64
|
+
# @param [ String | Mongoid::Document | nil ] name_or_class the value to coerce
|
65
|
+
#
|
66
|
+
# @return [ Mongoid::Document ] the resulting class
|
67
|
+
def class_from(name_or_class)
|
68
|
+
case name_or_class
|
69
|
+
when nil, false then association.klass
|
70
|
+
when String then name_or_class.constantize
|
71
|
+
else name_or_class
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
62
75
|
# Extracts and converts the id to the expected type.
|
63
76
|
#
|
64
77
|
# @return [ BSON::ObjectId | String | Object | nil ] The converted id,
|
@@ -23,7 +23,13 @@ module Mongoid
|
|
23
23
|
binding do
|
24
24
|
check_polymorphic_inverses!(_target)
|
25
25
|
bind_foreign_key(_base, record_id(_target))
|
26
|
-
|
26
|
+
|
27
|
+
# set the inverse type (e.g. "#{name}_type") for new polymorphic associations
|
28
|
+
if _association.inverse_type && !_base.frozen?
|
29
|
+
key = _association.resolver.default_key_for(_target)
|
30
|
+
bind_polymorphic_inverse_type(_base, key)
|
31
|
+
end
|
32
|
+
|
27
33
|
if inverse = _association.inverse(_target)
|
28
34
|
if set_base_association
|
29
35
|
if _base.referenced_many?
|
@@ -33,7 +33,7 @@ module Mongoid
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def query_criteria(object, type)
|
36
|
-
cls = type ? type.constantize : relation_class
|
36
|
+
cls = type ? (type.is_a?(String) ? type.constantize : type) : relation_class
|
37
37
|
crit = cls.criteria
|
38
38
|
crit = crit.apply_scope(scope)
|
39
39
|
crit.where(primary_key => object)
|
@@ -103,6 +103,21 @@ module Mongoid
|
|
103
103
|
@polymorphic ||= !!@options[:polymorphic]
|
104
104
|
end
|
105
105
|
|
106
|
+
# Returns the object responsible for converting polymorphic type references into
|
107
|
+
# class objects, and vice versa. This is obtained via the `:polymorphic` option
|
108
|
+
# that was given when the association was defined.
|
109
|
+
#
|
110
|
+
# See Mongoid::ModelResolver.resolver for how the `:polymorphic` option is
|
111
|
+
# interpreted here.
|
112
|
+
#
|
113
|
+
# @raise KeyError if no such resolver has been registered under the given
|
114
|
+
# identifier.
|
115
|
+
#
|
116
|
+
# @return [ nil | Mongoid::ModelResolver ] the resolver to use
|
117
|
+
def resolver
|
118
|
+
@resolver ||= Mongoid::ModelResolver.resolver(@options[:polymorphic])
|
119
|
+
end
|
120
|
+
|
106
121
|
# The name of the field used to store the type of polymorphic association.
|
107
122
|
#
|
108
123
|
# @return [ String ] The field used to store the type of polymorphic association.
|
@@ -6,6 +6,7 @@ require 'mongoid/association/referenced/has_many/buildable'
|
|
6
6
|
require 'mongoid/association/referenced/has_many/proxy'
|
7
7
|
require 'mongoid/association/referenced/has_many/enumerable'
|
8
8
|
require 'mongoid/association/referenced/has_many/eager'
|
9
|
+
require 'mongoid/association/referenced/with_polymorphic_criteria'
|
9
10
|
|
10
11
|
module Mongoid
|
11
12
|
module Association
|
@@ -15,6 +16,7 @@ module Mongoid
|
|
15
16
|
class HasMany
|
16
17
|
include Relatable
|
17
18
|
include Buildable
|
19
|
+
include WithPolymorphicCriteria
|
18
20
|
|
19
21
|
# The options available for this type of association, in addition to the
|
20
22
|
# common ones.
|
@@ -131,6 +133,12 @@ module Mongoid
|
|
131
133
|
# @param [ Class ] object_class The object class.
|
132
134
|
#
|
133
135
|
# @return [ Mongoid::Criteria ] The criteria object.
|
136
|
+
#
|
137
|
+
# @deprecated in 9.0.x
|
138
|
+
#
|
139
|
+
# It appears as if this method is an artifact left over from a refactoring that renamed it
|
140
|
+
# `with_polymorphic_criterion`, and made it private. Regardless, this method isn't referenced
|
141
|
+
# anywhere else, and is unlikely to be useful to external clients. We should remove it.
|
134
142
|
def add_polymorphic_criterion(criteria, object_class)
|
135
143
|
if polymorphic?
|
136
144
|
criteria.where(type => object_class.name)
|
@@ -138,6 +146,7 @@ module Mongoid
|
|
138
146
|
criteria
|
139
147
|
end
|
140
148
|
end
|
149
|
+
Mongoid.deprecate(self, :add_polymorphic_criterion)
|
141
150
|
|
142
151
|
# Is this association polymorphic?
|
143
152
|
#
|
@@ -222,14 +231,6 @@ module Mongoid
|
|
222
231
|
with_ordering(crit)
|
223
232
|
end
|
224
233
|
|
225
|
-
def with_polymorphic_criterion(criteria, base)
|
226
|
-
if polymorphic?
|
227
|
-
criteria.where(type => base.class.name)
|
228
|
-
else
|
229
|
-
criteria
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
234
|
def with_ordering(criteria)
|
234
235
|
if order
|
235
236
|
criteria.order_by(order)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# rubocop:todo all
|
3
3
|
|
4
|
+
require 'mongoid/association/referenced/with_polymorphic_criteria'
|
5
|
+
|
4
6
|
module Mongoid
|
5
7
|
module Association
|
6
8
|
module Referenced
|
@@ -8,6 +10,7 @@ module Mongoid
|
|
8
10
|
|
9
11
|
# The Builder behavior for has_one associations.
|
10
12
|
module Buildable
|
13
|
+
include WithPolymorphicCriteria
|
11
14
|
|
12
15
|
# This method either takes an _id or an object and queries for the
|
13
16
|
# inverse side using the id or sets the object after clearing the
|
@@ -57,14 +60,6 @@ module Mongoid
|
|
57
60
|
query_criteria(object, base).take
|
58
61
|
end
|
59
62
|
|
60
|
-
def with_polymorphic_criterion(criteria, base)
|
61
|
-
if polymorphic?
|
62
|
-
criteria.where(type => base.class.name)
|
63
|
-
else
|
64
|
-
criteria
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
63
|
def query?(object)
|
69
64
|
object && !object.is_a?(Mongoid::Document)
|
70
65
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Association
|
5
|
+
module Referenced
|
6
|
+
# Implements the `with_polymorphic_criteria` shared behavior.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
module WithPolymorphicCriteria
|
10
|
+
# If the receiver represents a polymorphic association, applies
|
11
|
+
# the polymorphic search criteria to the given `criteria` object.
|
12
|
+
#
|
13
|
+
# @param [ Mongoid::Criteria ] criteria the criteria to append to
|
14
|
+
# if receiver is polymorphic.
|
15
|
+
# @param [ Mongoid::Document ] base the document to use when resolving
|
16
|
+
# the polymorphic type keys.
|
17
|
+
#
|
18
|
+
# @return [ Mongoid::Criteria] the resulting criteria, which may be
|
19
|
+
# the same as the input.
|
20
|
+
def with_polymorphic_criterion(criteria, base)
|
21
|
+
if polymorphic?
|
22
|
+
# 1. get the resolver for the inverse association
|
23
|
+
resolver = klass.reflect_on_association(as).resolver
|
24
|
+
|
25
|
+
# 2. look up the list of keys from the resolver, given base
|
26
|
+
keys = resolver.keys_for(base)
|
27
|
+
|
28
|
+
# 3. use equality if there is just one key, `in` if there are multiple
|
29
|
+
if keys.many?
|
30
|
+
criteria.where(type => { :$in => keys })
|
31
|
+
else
|
32
|
+
criteria.where(type => keys.first)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
criteria
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -60,7 +60,8 @@ module Mongoid
|
|
60
60
|
re_define_method(meth) do |attrs|
|
61
61
|
_assigning do
|
62
62
|
if association.polymorphic? and association.inverse_type
|
63
|
-
|
63
|
+
klass = association.resolver.model_for(send(association.inverse_type))
|
64
|
+
options = options.merge!(:class_name => klass)
|
64
65
|
end
|
65
66
|
association.nested_builder(attrs, options).build(self)
|
66
67
|
end
|
@@ -89,21 +89,22 @@ module Mongoid
|
|
89
89
|
def transaction(options = {}, session_options: {})
|
90
90
|
with_session(session_options) do |session|
|
91
91
|
begin
|
92
|
-
session.
|
93
|
-
|
94
|
-
|
92
|
+
session.with_transaction(options) do
|
93
|
+
yield
|
94
|
+
end
|
95
|
+
run_commit_callbacks(session)
|
95
96
|
rescue *transactions_not_supported_exceptions
|
96
97
|
raise Mongoid::Errors::TransactionsNotSupported
|
97
98
|
rescue Mongoid::Errors::Rollback
|
98
|
-
|
99
|
+
run_abort_callbacks(session)
|
99
100
|
rescue Mongoid::Errors::InvalidSessionNesting
|
100
101
|
# Session should be ended here.
|
101
102
|
raise Mongoid::Errors::InvalidTransactionNesting.new
|
102
103
|
rescue Mongo::Error::InvalidSession, Mongo::Error::InvalidTransactionOperation => e
|
103
|
-
|
104
|
-
raise Mongoid::Errors::TransactionError(e)
|
104
|
+
run_abort_callbacks(session)
|
105
|
+
raise Mongoid::Errors::TransactionError.new(e)
|
105
106
|
rescue StandardError => e
|
106
|
-
|
107
|
+
run_abort_callbacks(session)
|
107
108
|
raise e
|
108
109
|
end
|
109
110
|
end
|
@@ -189,25 +190,21 @@ module Mongoid
|
|
189
190
|
_session&.in_transaction? || false
|
190
191
|
end
|
191
192
|
|
192
|
-
#
|
193
|
-
# after_commit callbacks on modified documents.
|
193
|
+
# Runs after_commit callbacks on modified documents.
|
194
194
|
#
|
195
195
|
# @param [ Mongo::Session ] session Session on which
|
196
196
|
# a transaction is started.
|
197
|
-
def
|
198
|
-
session.commit_transaction
|
197
|
+
def run_commit_callbacks(session)
|
199
198
|
Threaded.clear_modified_documents(session).each do |doc|
|
200
199
|
doc.run_after_callbacks(:commit)
|
201
200
|
end
|
202
201
|
end
|
203
202
|
|
204
|
-
#
|
205
|
-
# after_rollback callbacks on modified documents.
|
203
|
+
# Runs after_rollback callbacks on modified documents.
|
206
204
|
#
|
207
205
|
# @param [ Mongo::Session ] session Session on which
|
208
206
|
# a transaction is started.
|
209
|
-
def
|
210
|
-
session.abort_transaction
|
207
|
+
def run_abort_callbacks(session)
|
211
208
|
Threaded.clear_modified_documents(session).each do |doc|
|
212
209
|
doc.run_after_callbacks(:rollback)
|
213
210
|
end
|
data/lib/mongoid/composable.rb
CHANGED
@@ -5,6 +5,7 @@ require "mongoid/changeable"
|
|
5
5
|
require "mongoid/collection_configurable"
|
6
6
|
require "mongoid/encryptable"
|
7
7
|
require "mongoid/findable"
|
8
|
+
require 'mongoid/identifiable'
|
8
9
|
require "mongoid/indexable"
|
9
10
|
require "mongoid/inspectable"
|
10
11
|
require "mongoid/interceptable"
|
@@ -44,6 +45,7 @@ module Mongoid
|
|
44
45
|
include Attributes
|
45
46
|
include Evolvable
|
46
47
|
include Fields
|
48
|
+
include Identifiable
|
47
49
|
include Indexable
|
48
50
|
include Inspectable
|
49
51
|
include Matchable
|
data/lib/mongoid/document.rb
CHANGED
@@ -17,6 +17,7 @@ require 'mongoid/timestamps'
|
|
17
17
|
require 'mongoid/association'
|
18
18
|
require 'mongoid/composable'
|
19
19
|
require 'mongoid/touchable'
|
20
|
+
require 'mongoid/model_resolver'
|
20
21
|
|
21
22
|
module Mongoid
|
22
23
|
# This is the base module for all domain objects that need to be persisted to
|
@@ -31,6 +32,7 @@ module Mongoid
|
|
31
32
|
|
32
33
|
included do
|
33
34
|
Mongoid.register_model(self)
|
35
|
+
Mongoid::ModelResolver.register(self)
|
34
36
|
end
|
35
37
|
|
36
38
|
# Regex for matching illegal BSON keys.
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Errors
|
5
|
+
# Raised when a polymorphic association is queried, but the type of the
|
6
|
+
# association cannot be resolved. This usually happens when the data in
|
7
|
+
# the database references a type that no longer exists.
|
8
|
+
#
|
9
|
+
# For example, consider the following model:
|
10
|
+
#
|
11
|
+
# class Manager
|
12
|
+
# include Mongoid::Document
|
13
|
+
# belongs_to :unit, polymorphic: true
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Imagine there is a document in the `managers` collection that looks
|
17
|
+
# something like this:
|
18
|
+
#
|
19
|
+
# { _id: ..., unit_id: ..., unit_type: 'Department::Engineering' }
|
20
|
+
#
|
21
|
+
# If, at some point in your refactoring, you rename the `Department::Engineering`
|
22
|
+
# model to something else, Mongoid will no longer be able to resolve the
|
23
|
+
# type of this association, and asking for `manager.unit` will raise this
|
24
|
+
# exception.
|
25
|
+
#
|
26
|
+
# To fix this exception, you can add an alias to the model class so that it
|
27
|
+
# can still be found, even after renaming it:
|
28
|
+
#
|
29
|
+
# module Engineering
|
30
|
+
# class Department
|
31
|
+
# include Mongoid::Document
|
32
|
+
#
|
33
|
+
# identify_as 'Department::Engineering'
|
34
|
+
#
|
35
|
+
# # ...
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Better practice would be to use unique strings instead of class names to
|
40
|
+
# identify these polymorphic types in the database (e.g. 'dept' instead of
|
41
|
+
# 'Department::Engineering').
|
42
|
+
class UnrecognizedModelAlias < MongoidError
|
43
|
+
def initialize(model_alias)
|
44
|
+
super(
|
45
|
+
compose_message(
|
46
|
+
'unrecognized_model_alias',
|
47
|
+
model_alias: model_alias.inspect
|
48
|
+
)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Errors
|
5
|
+
# Raised when a model resolver is referenced, but not registered.
|
6
|
+
#
|
7
|
+
# class Manager
|
8
|
+
# include Mongoid::Document
|
9
|
+
# belongs_to :unit, polymorphic: :org
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# If `:org` has not previously been registered as a model resolver,
|
13
|
+
# Mongoid will raise UnrecognizedResolver when it tries to resolve
|
14
|
+
# a manager's unit.
|
15
|
+
class UnrecognizedResolver < MongoidError
|
16
|
+
def initialize(resolver)
|
17
|
+
super(
|
18
|
+
compose_message(
|
19
|
+
'unrecognized_resolver',
|
20
|
+
resolver: resolver.inspect,
|
21
|
+
resolvers: [ :default, *Mongoid::ModelResolver.resolvers.keys ].inspect
|
22
|
+
)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Errors
|
5
|
+
# Raised when Mongoid tries to query the identifier to use for a given
|
6
|
+
# class in a polymorphic association, but the class has not previously
|
7
|
+
# been registered by resolver that was used for the query.
|
8
|
+
#
|
9
|
+
# Here's an exammple:
|
10
|
+
#
|
11
|
+
# class Department
|
12
|
+
# include Mongoid::Document
|
13
|
+
# has_many :managers, as: :unit
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# class Manager
|
17
|
+
# include Mongoid::Document
|
18
|
+
# belongs_to :unit, polymorphic: :org
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# The Manager class is configured to use a custom resolver named `:org`
|
22
|
+
# when resolving the polymorphic `unit` association. However, the `Department`
|
23
|
+
# class is not registered with that resolver. When the program tries to
|
24
|
+
# associate a manager record with a department, it will not be able to find
|
25
|
+
# the required key in the `:org` resolver, and will fail with this exception.
|
26
|
+
#
|
27
|
+
# The solution is to make sure the `Department` class is properly registered
|
28
|
+
# with the `:org` resolver:
|
29
|
+
#
|
30
|
+
# class Department
|
31
|
+
# include Mongoid::Document
|
32
|
+
# identify_as resolver: :org
|
33
|
+
# has_many :managers, as: :unit
|
34
|
+
# end
|
35
|
+
class UnregisteredClass < MongoidError
|
36
|
+
def initialize(klass, resolver)
|
37
|
+
super(
|
38
|
+
compose_message(
|
39
|
+
'unregistered_class',
|
40
|
+
klass: klass,
|
41
|
+
resolver: resolver.inspect
|
42
|
+
)
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/mongoid/errors.rb
CHANGED
@@ -69,6 +69,9 @@ require "mongoid/errors/transaction_error"
|
|
69
69
|
require "mongoid/errors/transactions_not_supported"
|
70
70
|
require "mongoid/errors/unknown_attribute"
|
71
71
|
require "mongoid/errors/unknown_model"
|
72
|
+
require 'mongoid/errors/unrecognized_model_alias'
|
73
|
+
require 'mongoid/errors/unrecognized_resolver'
|
74
|
+
require 'mongoid/errors/unregistered_class'
|
72
75
|
require "mongoid/errors/unsaved_document"
|
73
76
|
require "mongoid/errors/unsupported_javascript"
|
74
77
|
require "mongoid/errors/validations"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mongoid/model_resolver'
|
4
|
+
|
5
|
+
module Mongoid
|
6
|
+
# Implements the "identify_as" interface (for specifying type aliases
|
7
|
+
# for document classes).
|
8
|
+
module Identifiable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
# Specifies aliases that may be used to identify this document
|
13
|
+
# class in polymorphic situations. By default, classes are identified
|
14
|
+
# by their class names, but alternative aliases may be used instead,
|
15
|
+
# if desired.
|
16
|
+
#
|
17
|
+
# @param [ Array<String | Symbol> ] aliases the list of aliases to
|
18
|
+
# assign to this class.
|
19
|
+
# @param [ Mongoid::ModelResolver::Interface | Symbol | :default ] resolver the
|
20
|
+
# resolver instance to use when registering the type. If :default, the default
|
21
|
+
# `ModelResolver` instance will be used. If any other symbol, it must identify a
|
22
|
+
# previously registered ModelResolver instance.
|
23
|
+
def identify_as(*aliases, resolver: :default)
|
24
|
+
Mongoid::ModelResolver.resolver(resolver).register(self, *aliases)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|