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
@@ -0,0 +1,154 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Mongoid
|
6
|
+
# The default class for resolving model classes based on discriminant keys.
|
7
|
+
# Given a key, it will return the corresponding model class, if any. By
|
8
|
+
# default, it looks for classes with names that match the given keys, but
|
9
|
+
# additional mappings may be provided.
|
10
|
+
#
|
11
|
+
# It is also possible to instantiate multiple resolvers---and even implement
|
12
|
+
# your own---so that different sets of classes can use independent resolution
|
13
|
+
# mechanics.
|
14
|
+
class ModelResolver
|
15
|
+
# The mutex instance used to make the `.instance` method thread-safe.
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
INSTANCE_MUTEX = Mutex.new
|
19
|
+
|
20
|
+
class << self
|
21
|
+
extend Forwardable
|
22
|
+
def_delegators :instance, :register
|
23
|
+
|
24
|
+
# Returns the default instance of the ModelResolver.
|
25
|
+
#
|
26
|
+
# @return [ Mongoid::ModelResolver ] the default ModelResolver instance.
|
27
|
+
def instance
|
28
|
+
@instance ||= INSTANCE_MUTEX.synchronize { @instance ||= new }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the map of registered resolvers. The default resolver is not
|
32
|
+
# included here.
|
33
|
+
#
|
34
|
+
# @return [ Hash<Symbol => Mongoid::ModelResolver::Interface> ] the hash of
|
35
|
+
# resolver instances, mapped by symbol identifier.
|
36
|
+
def resolvers
|
37
|
+
@resolvers ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the resolver instance that corresponds to the argument.
|
41
|
+
#
|
42
|
+
# @param [ nil | true | false Symbol | String | Mongoid::ModelResolver::Interface ] identifier_or_object
|
43
|
+
# When nil or false, returns nil. When true or :default, corresponds to the default resolver.
|
44
|
+
# When any other symbol or string, corresponds to the registered resolver with that identifier.
|
45
|
+
# Otherwise, it must be a resolver instance itself.
|
46
|
+
#
|
47
|
+
# @raise Mongoid::Errors::UnrecognizedResolver if the given identifier is a
|
48
|
+
# symbol or string and it does not match any registered resolver.
|
49
|
+
#
|
50
|
+
# @return [ Mongoid::ModelResolver::Interface ] the resolver instance corresponding to the
|
51
|
+
# given argument.
|
52
|
+
def resolver(identifier_or_object = :default)
|
53
|
+
case identifier_or_object
|
54
|
+
when nil, false then nil
|
55
|
+
when true, :default then instance
|
56
|
+
when String, Symbol
|
57
|
+
resolvers.fetch(identifier_or_object.to_sym) do |key|
|
58
|
+
raise Mongoid::Errors::UnrecognizedResolver, key
|
59
|
+
end
|
60
|
+
else identifier_or_object
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Register the given resolver under the given name.
|
65
|
+
#
|
66
|
+
# @param [ Mongoid::ModelResolver::Interface ] resolver the resolver to register.
|
67
|
+
# @param [ String | Symbol ] name the identifier to use to register the resolver.
|
68
|
+
def register_resolver(resolver, name)
|
69
|
+
resolvers[name.to_sym] = resolver
|
70
|
+
self
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Instantiates a new ModelResolver instance.
|
75
|
+
def initialize
|
76
|
+
@key_to_model = {}
|
77
|
+
@model_to_keys = {}
|
78
|
+
end
|
79
|
+
|
80
|
+
# Registers the given model class with the given keys. In addition to the given keys, the
|
81
|
+
# class name itself will be included as a key to identify the class. Keys are given in priority
|
82
|
+
# order, with highest priority keys first and lowest last. The class name, if not given explicitly,
|
83
|
+
# is always given lowest priority.
|
84
|
+
#
|
85
|
+
# If called more than once, newer keys have higher priority than older keys. All duplicate keys will
|
86
|
+
# be removed.
|
87
|
+
#
|
88
|
+
# @param [ Mongoid::Document ] klass the document class to register
|
89
|
+
# @param [ Array<String> ] *keys the list of keys to use as an alias (optional)
|
90
|
+
def register(klass, *keys)
|
91
|
+
default_key = klass.name
|
92
|
+
|
93
|
+
@model_to_keys[klass] = [ *keys, *@model_to_keys[klass], default_key ].uniq
|
94
|
+
@key_to_model[default_key] = klass
|
95
|
+
|
96
|
+
keys.each do |key|
|
97
|
+
@key_to_model[key] = klass
|
98
|
+
end
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
# The `Interface` concern represents the interface that custom resolvers
|
104
|
+
# must implement.
|
105
|
+
concerning :Interface do
|
106
|
+
# Returns the default (highest priority) key for the given record. This is typically
|
107
|
+
# the key that will be used when saving a new polymorphic association.
|
108
|
+
#
|
109
|
+
# @param [ Mongoid::Document ] record the record instance for which to query the default key.
|
110
|
+
#
|
111
|
+
# @raise Mongoid::Errors::UnregisteredClass if the record's class has not been registered with this resolver.
|
112
|
+
#
|
113
|
+
# @return [ String ] the default key for the record's class.
|
114
|
+
def default_key_for(record)
|
115
|
+
keys_for(record).first
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the list of all keys for the given record's class, in priority order (with highest
|
119
|
+
# priority keys first).
|
120
|
+
#
|
121
|
+
# @param [ Mongoid::Document] record the record instance for which to query the registered keys.
|
122
|
+
#
|
123
|
+
# @raise Mongoid::Errors::UnregisteredClass if the record's class has not been registered with this resolver.
|
124
|
+
#
|
125
|
+
# @return [ Array<String> ] the list of keys that have been registered for the given class.
|
126
|
+
def keys_for(record)
|
127
|
+
@model_to_keys.fetch(record.class) do |klass|
|
128
|
+
# figure out which resolver this is
|
129
|
+
resolver = if self == Mongoid::ModelResolver.instance
|
130
|
+
:default
|
131
|
+
else
|
132
|
+
Mongoid::ModelResolver.resolvers.keys.detect { |k| Mongoid::ModelResolver.resolvers[k] == self }
|
133
|
+
end
|
134
|
+
resolver ||= self # if it hasn't been registered, we'll show it the best we can
|
135
|
+
raise Mongoid::Errors::UnregisteredClass.new(klass, resolver)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the document class that has been registered by the given key.
|
140
|
+
#
|
141
|
+
# @param [ String ] key the key by which to query the corresponding class.
|
142
|
+
#
|
143
|
+
# @raise Mongoid::Errors::UnrecognizedModelAlias if the given key has not
|
144
|
+
# been registered with this resolver.
|
145
|
+
#
|
146
|
+
# @return [ Class ] the document class that has been registered with the given key.
|
147
|
+
def model_for(key)
|
148
|
+
@key_to_model.fetch(key) do
|
149
|
+
raise Mongoid::Errors::UnrecognizedModelAlias, key
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -25,7 +25,8 @@ module Mongoid
|
|
25
25
|
# @return [ Array<Symbol> ] The list of extra options besides client options
|
26
26
|
# that determine the persistence context.
|
27
27
|
EXTRA_OPTIONS = [ :client,
|
28
|
-
:collection
|
28
|
+
:collection,
|
29
|
+
:collection_options
|
29
30
|
].freeze
|
30
31
|
|
31
32
|
# The full list of valid persistence context options.
|
data/lib/mongoid/traversable.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'mongoid/fields/validators/macro'
|
4
|
+
require 'mongoid/model_resolver'
|
4
5
|
|
5
6
|
module Mongoid
|
6
7
|
# Mixin module included in Mongoid::Document to provide behavior
|
@@ -32,6 +33,10 @@ module Mongoid
|
|
32
33
|
# rubocop:disable Metrics/AbcSize
|
33
34
|
def inherited(subclass)
|
34
35
|
super
|
36
|
+
|
37
|
+
# Register the new subclass with the resolver subsystem
|
38
|
+
Mongoid::ModelResolver.register(subclass)
|
39
|
+
|
35
40
|
@_type = nil
|
36
41
|
subclass.aliased_fields = aliased_fields.dup
|
37
42
|
subclass.localized_fields = localized_fields.dup
|
data/lib/mongoid/version.rb
CHANGED
@@ -2,8 +2,40 @@
|
|
2
2
|
# rubocop:todo all
|
3
3
|
|
4
4
|
require 'spec_helper'
|
5
|
+
require 'support/feature_sandbox'
|
6
|
+
|
5
7
|
require_relative '../../mongoid/association/referenced/has_one_models'
|
6
8
|
|
9
|
+
def quarantine(context, polymorphic:, dept_aliases:, team_aliases:)
|
10
|
+
state = {}
|
11
|
+
|
12
|
+
context.before(:context) do
|
13
|
+
state[:quarantine] = FeatureSandbox.start_quarantine
|
14
|
+
|
15
|
+
# Have to eval this, because otherwise we get syntax errors when defining a class
|
16
|
+
# inside a method.
|
17
|
+
#
|
18
|
+
# I know the scissors are sharp! But I want to run with them anwyay!
|
19
|
+
Object.class_eval <<-RUBY
|
20
|
+
class SandboxManager; include Mongoid::Document; end
|
21
|
+
class SandboxDepartment; include Mongoid::Document; end
|
22
|
+
class SandboxTeam; include Mongoid::Document; end
|
23
|
+
RUBY
|
24
|
+
|
25
|
+
SandboxManager.belongs_to :unit, polymorphic: polymorphic
|
26
|
+
|
27
|
+
SandboxDepartment.identify_as *dept_aliases, resolver: polymorphic
|
28
|
+
SandboxDepartment.has_many :sandbox_managers, as: :unit
|
29
|
+
|
30
|
+
SandboxTeam.identify_as *team_aliases, resolver: polymorphic
|
31
|
+
SandboxTeam.has_one :sandbox_manager, as: :unit
|
32
|
+
end
|
33
|
+
|
34
|
+
context.after(:context) do
|
35
|
+
FeatureSandbox.end_quarantine(state[:quarantine])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
7
39
|
describe 'belongs_to associations' do
|
8
40
|
context 'referencing top level classes when source class is namespaced' do
|
9
41
|
let(:college) { HomCollege.create! }
|
@@ -31,4 +63,101 @@ describe 'belongs_to associations' do
|
|
31
63
|
expect(instance.movie).to eq movie
|
32
64
|
end
|
33
65
|
end
|
66
|
+
|
67
|
+
context 'when the association is polymorphic' do
|
68
|
+
let(:dept_manager) { SandboxManager.create(unit: department) }
|
69
|
+
let(:team_manager) { SandboxManager.create(unit: team) }
|
70
|
+
let(:department) { SandboxDepartment.create }
|
71
|
+
let(:team) { SandboxTeam.create }
|
72
|
+
|
73
|
+
shared_context 'it finds the associated records' do
|
74
|
+
it 'successfully finds the manager\'s unit' do
|
75
|
+
expect(dept_manager.reload.unit).to be == department
|
76
|
+
expect(team_manager.reload.unit).to be == team
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'successfully finds the unit\'s manager' do
|
80
|
+
dept_manager; team_manager # make sure these are created first...
|
81
|
+
|
82
|
+
expect(department.reload.sandbox_managers).to be == [ dept_manager ]
|
83
|
+
expect(team.reload.sandbox_manager).to be == team_manager
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
shared_context 'it searches for alternative aliases' do
|
88
|
+
it 'successfully finds the corresponding unit when unit_type is a different alias' do
|
89
|
+
dept_manager.update unit_type: 'sandbox_dept'
|
90
|
+
dept_manager.reload
|
91
|
+
|
92
|
+
team_manager.update unit_type: 'group'
|
93
|
+
team_manager.reload
|
94
|
+
|
95
|
+
expect(dept_manager.reload.unit_type).to be == 'sandbox_dept'
|
96
|
+
expect(dept_manager.unit).to be == department
|
97
|
+
|
98
|
+
expect(team_manager.reload.unit_type).to be == 'group'
|
99
|
+
expect(team_manager.unit).to be == team
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'when the association uses the default resolver' do
|
104
|
+
context 'when there are no aliases given' do
|
105
|
+
quarantine(self, polymorphic: true, dept_aliases: [], team_aliases: [])
|
106
|
+
|
107
|
+
it 'populates the unit_type with the class name' do
|
108
|
+
expect(dept_manager.unit_type).to be == 'SandboxDepartment'
|
109
|
+
expect(team_manager.unit_type).to be == 'SandboxTeam'
|
110
|
+
end
|
111
|
+
|
112
|
+
it_behaves_like 'it finds the associated records'
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when there are multiple aliases given' do
|
116
|
+
quarantine(self, polymorphic: true, dept_aliases: %w[ dept sandbox_dept ], team_aliases: %w[ team group ])
|
117
|
+
|
118
|
+
it 'populates the unit_type with the first alias' do
|
119
|
+
expect(dept_manager.unit_type).to be == 'dept'
|
120
|
+
expect(team_manager.unit_type).to be == 'team'
|
121
|
+
end
|
122
|
+
|
123
|
+
it_behaves_like 'it finds the associated records'
|
124
|
+
it_behaves_like 'it searches for alternative aliases'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when the association uses a registered resolver' do
|
129
|
+
before(:context) { Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, :sandbox }
|
130
|
+
quarantine(self, polymorphic: :sandbox, dept_aliases: %w[ dept sandbox_dept ], team_aliases: %w[ team group ])
|
131
|
+
|
132
|
+
it 'does not include the aliases in the default resolver' do
|
133
|
+
expect(Mongoid::ModelResolver.instance.keys_for(SandboxDepartment.new)).not_to include('dept')
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'populates the unit_type with the first alias' do
|
137
|
+
expect(dept_manager.unit_type).to be == 'dept'
|
138
|
+
expect(team_manager.unit_type).to be == 'team'
|
139
|
+
end
|
140
|
+
|
141
|
+
it_behaves_like 'it finds the associated records'
|
142
|
+
it_behaves_like 'it searches for alternative aliases'
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when the association uses an unregistered resolver' do
|
146
|
+
quarantine(self, polymorphic: Mongoid::ModelResolver.new,
|
147
|
+
dept_aliases: %w[ dept sandbox_dept ],
|
148
|
+
team_aliases: %w[ team group ])
|
149
|
+
|
150
|
+
it 'does not include the aliases in the default resolver' do
|
151
|
+
expect(Mongoid::ModelResolver.instance.keys_for(SandboxDepartment.new)).not_to include('dept')
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'populates the unit_type with the first alias' do
|
155
|
+
expect(dept_manager.unit_type).to be == 'dept'
|
156
|
+
expect(team_manager.unit_type).to be == 'team'
|
157
|
+
end
|
158
|
+
|
159
|
+
it_behaves_like 'it finds the associated records'
|
160
|
+
it_behaves_like 'it searches for alternative aliases'
|
161
|
+
end
|
162
|
+
end
|
34
163
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
# rubocop:disable RSpec/LeakyConstantDeclaration
|
6
|
+
# rubocop:disable Lint/ConstantDefinitionInBlock
|
7
|
+
describe 'Collection options' do
|
8
|
+
before(:all) do
|
9
|
+
class CollectionOptionsCapped
|
10
|
+
include Mongoid::Document
|
11
|
+
|
12
|
+
store_in collection_options: {
|
13
|
+
capped: true,
|
14
|
+
size: 25_600
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
after(:all) do
|
20
|
+
CollectionOptionsCapped.collection.drop
|
21
|
+
Mongoid.deregister_model(CollectionOptionsCapped)
|
22
|
+
Object.send(:remove_const, :CollectionOptionsCapped)
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
CollectionOptionsCapped.collection.drop
|
27
|
+
# We should create the collection explicitly to apply collection options.
|
28
|
+
CollectionOptionsCapped.create_collection
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates a document' do
|
32
|
+
expect { CollectionOptionsCapped.create! }.not_to raise_error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
# rubocop:enable Lint/ConstantDefinitionInBlock
|
36
|
+
# rubocop:enable RSpec/LeakyConstantDeclaration
|
@@ -28,6 +28,10 @@ describe Mongoid::Association::Embedded::EmbedsMany do
|
|
28
28
|
expect(legislator.attributes.keys).to eq(['_id', 'a'])
|
29
29
|
end
|
30
30
|
|
31
|
+
it 'allows accessing the parent' do
|
32
|
+
expect { legislator.congress }.not_to raise_error
|
33
|
+
end
|
34
|
+
|
31
35
|
context 'when using only with $' do
|
32
36
|
before do
|
33
37
|
Patient.destroy_all
|
@@ -4,6 +4,10 @@
|
|
4
4
|
require "spec_helper"
|
5
5
|
require_relative './has_one_models'
|
6
6
|
|
7
|
+
BELONGS_TO_RESOLVER_ID__ = :__belongs_to_resolver_id
|
8
|
+
BELONGS_TO_RESOLVER = Mongoid::ModelResolver.new
|
9
|
+
Mongoid::ModelResolver.register_resolver BELONGS_TO_RESOLVER, BELONGS_TO_RESOLVER_ID__
|
10
|
+
|
7
11
|
describe Mongoid::Association::Referenced::BelongsTo do
|
8
12
|
|
9
13
|
before do
|
@@ -199,47 +203,76 @@ describe Mongoid::Association::Referenced::BelongsTo do
|
|
199
203
|
|
200
204
|
context 'when the polymorphic option is provided' do
|
201
205
|
|
202
|
-
|
206
|
+
[ true, :default ].each do |opt|
|
207
|
+
context "when the polymorphic option is #{opt.inspect}" do
|
208
|
+
let(:options) { { polymorphic: opt } }
|
209
|
+
before { association }
|
203
210
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
211
|
+
it 'set the polymorphic attribute on the owner class' do
|
212
|
+
expect(belonging_class.polymorphic).to be(true)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'sets up a field for the inverse type' do
|
216
|
+
expect(belonging_class.fields.keys).to include(association.inverse_type)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'uses the default resolver' do
|
220
|
+
expect(association.resolver).to be == Mongoid::ModelResolver.instance
|
221
|
+
end
|
208
222
|
end
|
223
|
+
end
|
209
224
|
|
210
|
-
|
211
|
-
|
225
|
+
[ false, nil ].each do |opt|
|
226
|
+
context "when the polymorphic option is #{opt.inspect}" do
|
227
|
+
let(:options) { { polymorphic: opt } }
|
228
|
+
|
229
|
+
it 'does not set the polymorphic attribute on the owner class' do
|
230
|
+
expect(belonging_class.polymorphic).to be(false)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'does not set up a field for the inverse type' do
|
234
|
+
expect(belonging_class.fields.keys).not_to include(association.inverse_type)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'does not use a resolver' do
|
238
|
+
expect(association.resolver).to be_nil
|
239
|
+
end
|
212
240
|
end
|
241
|
+
end
|
213
242
|
|
214
|
-
|
215
|
-
|
243
|
+
context 'when the polymorphic option is set to an unregistered id' do
|
244
|
+
let(:options) { { polymorphic: :bogus } }
|
245
|
+
|
246
|
+
# This behavior is intentional, so that the resolver can be registered after the classes
|
247
|
+
# are loaded.
|
248
|
+
it 'does not immediately raise an exception' do
|
249
|
+
expect { association }.not_to raise_error
|
216
250
|
end
|
217
251
|
|
218
|
-
it '
|
219
|
-
expect
|
252
|
+
it 'raises error when resolver is accessed' do
|
253
|
+
expect { association.resolver }.to raise_error(Mongoid::Errors::UnrecognizedResolver)
|
220
254
|
end
|
221
255
|
end
|
222
256
|
|
223
|
-
context 'when the polymorphic option is
|
257
|
+
context 'when the polymorphic option is set to a registered id' do
|
258
|
+
let(:options) { { polymorphic: BELONGS_TO_RESOLVER_ID__ } }
|
259
|
+
before { association }
|
224
260
|
|
225
|
-
|
226
|
-
|
227
|
-
polymorphic: false
|
228
|
-
}
|
261
|
+
it 'set the polymorphic attribute on the owner class' do
|
262
|
+
expect(belonging_class.polymorphic).to be(true)
|
229
263
|
end
|
230
264
|
|
231
|
-
it '
|
232
|
-
expect(belonging_class.
|
265
|
+
it 'sets up a field for the inverse type' do
|
266
|
+
expect(belonging_class.fields.keys).to include(association.inverse_type)
|
233
267
|
end
|
234
268
|
|
235
|
-
it '
|
236
|
-
expect(
|
269
|
+
it 'connects the association to the corresponding resolver' do
|
270
|
+
expect(association.resolver).to be == BELONGS_TO_RESOLVER
|
237
271
|
end
|
238
272
|
end
|
239
273
|
end
|
240
274
|
|
241
275
|
context 'when the polymorphic option is not provided' do
|
242
|
-
|
243
276
|
it 'does not set the polymorphic attribute on the owner class' do
|
244
277
|
expect(belonging_class.polymorphic).to be(false)
|
245
278
|
end
|
@@ -247,6 +280,10 @@ describe Mongoid::Association::Referenced::BelongsTo do
|
|
247
280
|
it 'does not set up a field for the inverse type' do
|
248
281
|
expect(belonging_class.fields.keys).not_to include(association.inverse_type)
|
249
282
|
end
|
283
|
+
|
284
|
+
it 'does not use a resolver' do
|
285
|
+
expect(association.resolver).to be_nil
|
286
|
+
end
|
250
287
|
end
|
251
288
|
end
|
252
289
|
|
@@ -100,6 +100,10 @@ describe Mongoid::Association::Referenced::HasMany::Buildable do
|
|
100
100
|
Post.where(association.foreign_key => object, 'ratable_type' => 'Rating')
|
101
101
|
end
|
102
102
|
|
103
|
+
before do
|
104
|
+
Post.belongs_to :ratable, polymorphic: true
|
105
|
+
end
|
106
|
+
|
103
107
|
it "adds the type to the criteria" do
|
104
108
|
expect(documents).to eq(criteria)
|
105
109
|
end
|
@@ -282,7 +282,7 @@ describe Mongoid::Clients::Sessions do
|
|
282
282
|
end
|
283
283
|
end
|
284
284
|
|
285
|
-
include_examples 'it aborts the transaction', Mongoid::Errors::
|
285
|
+
include_examples 'it aborts the transaction', Mongoid::Errors::TransactionError
|
286
286
|
end
|
287
287
|
end
|
288
288
|
end
|
@@ -591,7 +591,7 @@ describe Mongoid::Clients::Sessions do
|
|
591
591
|
end
|
592
592
|
|
593
593
|
it 'raises an error' do
|
594
|
-
expect(error).to be_a(Mongoid::Errors::
|
594
|
+
expect(error).to be_a(Mongoid::Errors::TransactionError)
|
595
595
|
end
|
596
596
|
|
597
597
|
it 'does not execute any operations' do
|