mongoid 9.0.1 → 9.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|