mongoid 9.0.0 → 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/README.md +2 -0
- data/Rakefile +44 -21
- data/lib/config/locales/en.yml +20 -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/atomic_update_preparer.rb +7 -6
- 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/config.rb +9 -0
- data/lib/mongoid/contextual/aggregable/memory.rb +3 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +5 -2
- data/lib/mongoid/criteria/findable.rb +2 -2
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -1
- data/lib/mongoid/document.rb +2 -0
- data/lib/mongoid/errors/invalid_around_callback.rb +16 -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 +4 -0
- data/lib/mongoid/fields.rb +13 -7
- data/lib/mongoid/identifiable.rb +28 -0
- data/lib/mongoid/interceptable.rb +18 -13
- data/lib/mongoid/model_resolver.rb +154 -0
- data/lib/mongoid/persistence_context.rb +2 -1
- data/lib/mongoid/scopable.rb +7 -1
- data/lib/mongoid/touchable.rb +1 -7
- 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/association_spec.rb +14 -0
- data/spec/mongoid/attributes/nested_spec.rb +1 -0
- data/spec/mongoid/attributes_spec.rb +16 -0
- data/spec/mongoid/clients/transactions_spec.rb +2 -2
- data/spec/mongoid/contextual/aggregable/memory_spec.rb +11 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +11 -0
- data/spec/mongoid/contextual/mongo_spec.rb +72 -3
- data/spec/mongoid/fields_spec.rb +2 -2
- data/spec/mongoid/interceptable_spec.rb +31 -0
- 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/scopable_spec.rb +88 -85
- data/spec/mongoid/serializable_spec.rb +16 -9
- data/spec/mongoid/touchable_spec.rb +75 -0
- data/spec/mongoid/touchable_spec_models.rb +16 -0
- data/spec/support/models/band.rb +1 -0
- data/spec/support/models/lat_lng.rb +6 -0
- metadata +20 -82
- checksums.yaml.gz.sig +0 -1
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/bin/s3-copy +0 -45
- data/spec/shared/bin/s3-upload +0 -69
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -231
- data/spec/shared/lib/mrss/constraints.rb +0 -378
- data/spec/shared/lib/mrss/docker_runner.rb +0 -298
- data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
- data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
- data/spec/shared/lib/mrss/session_registry.rb +0 -69
- data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
- data/spec/shared/lib/mrss/utils.rb +0 -37
- data/spec/shared/share/Dockerfile.erb +0 -281
- data/spec/shared/share/haproxy-1.conf +0 -16
- data/spec/shared/share/haproxy-2.conf +0 -17
- data/spec/shared/shlib/config.sh +0 -27
- data/spec/shared/shlib/distro.sh +0 -74
- data/spec/shared/shlib/server.sh +0 -417
- data/spec/shared/shlib/set_env.sh +0 -146
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -1
@@ -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
|
@@ -15,6 +15,20 @@ describe Mongoid::Association do
|
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
18
|
+
context "when class_name references an unknown class" do
|
19
|
+
context "when loading" do
|
20
|
+
it "does not raise an exception" do
|
21
|
+
expect do
|
22
|
+
class AssocationSpecModel
|
23
|
+
include Mongoid::Document
|
24
|
+
|
25
|
+
embedded_in :parent, class_name: 'SomethingBogusThatDoesNotExistYet'
|
26
|
+
end
|
27
|
+
end.not_to raise_exception
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
18
32
|
describe "#embedded?" do
|
19
33
|
|
20
34
|
let(:person) do
|
@@ -289,6 +289,22 @@ describe Mongoid::Attributes do
|
|
289
289
|
end
|
290
290
|
end
|
291
291
|
|
292
|
+
context "when given nil" do
|
293
|
+
|
294
|
+
it "returns nil" do
|
295
|
+
expect(person[nil]).to be nil
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
context "when given an empty string" do
|
301
|
+
|
302
|
+
it "returns nil" do
|
303
|
+
expect(person[""]).to be nil
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
292
308
|
context "when the field was not explicitly defined" do
|
293
309
|
|
294
310
|
context "when excluding with only and the field was not excluded" do
|
@@ -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
|
@@ -570,5 +570,16 @@ describe Mongoid::Contextual::Aggregable::Memory do
|
|
570
570
|
expect(sum).to eq(1500)
|
571
571
|
end
|
572
572
|
end
|
573
|
+
|
574
|
+
context "when provided a block with initial value" do
|
575
|
+
|
576
|
+
let(:sum) do
|
577
|
+
context.sum(500, &:likes)
|
578
|
+
end
|
579
|
+
|
580
|
+
it "returns the sum for the provided block starting from initial value" do
|
581
|
+
expect(sum).to eq(2000)
|
582
|
+
end
|
583
|
+
end
|
573
584
|
end
|
574
585
|
end
|
@@ -515,6 +515,17 @@ describe Mongoid::Contextual::Aggregable::Mongo do
|
|
515
515
|
expect(sum).to eq(1500)
|
516
516
|
end
|
517
517
|
end
|
518
|
+
|
519
|
+
context "when provided a block with initial value" do
|
520
|
+
|
521
|
+
let(:sum) do
|
522
|
+
context.sum(500, &:likes)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "returns the sum for the provided block starting from initial value" do
|
526
|
+
expect(sum).to eq(2000)
|
527
|
+
end
|
528
|
+
end
|
518
529
|
end
|
519
530
|
end
|
520
531
|
|
@@ -3640,6 +3640,75 @@ describe Mongoid::Contextual::Mongo do
|
|
3640
3640
|
expect(new_order.reload.genres).to eq(["electronic"])
|
3641
3641
|
end
|
3642
3642
|
end
|
3643
|
+
|
3644
|
+
context "when operation is $pull" do
|
3645
|
+
context "when pulling single element" do
|
3646
|
+
|
3647
|
+
before do
|
3648
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop"])
|
3649
|
+
new_order.update_attribute(:genres, ["electronic", "pop"])
|
3650
|
+
context.update_all("$pull" => { genres: "electronic" })
|
3651
|
+
end
|
3652
|
+
|
3653
|
+
it "updates the first matching document" do
|
3654
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3655
|
+
end
|
3656
|
+
|
3657
|
+
it "updates the last matching document" do
|
3658
|
+
expect(new_order.reload.genres).to eq(["pop"])
|
3659
|
+
end
|
3660
|
+
end
|
3661
|
+
|
3662
|
+
context "when pulling based on condition" do
|
3663
|
+
before do
|
3664
|
+
depeche_mode.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3665
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "dance"])
|
3666
|
+
context.update_all("$pull" => { genres: { '$in' => ["electronic", "pop"] } })
|
3667
|
+
end
|
3668
|
+
|
3669
|
+
it "updates the first matching document" do
|
3670
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3671
|
+
end
|
3672
|
+
|
3673
|
+
it "updates the last matching document" do
|
3674
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3675
|
+
end
|
3676
|
+
end
|
3677
|
+
end
|
3678
|
+
|
3679
|
+
context "when operation is $pop" do
|
3680
|
+
|
3681
|
+
before do
|
3682
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic"])
|
3683
|
+
end
|
3684
|
+
|
3685
|
+
it "removes first element in array" do
|
3686
|
+
context.update_all("$pop" => { genres: -1 })
|
3687
|
+
expect(depeche_mode.reload.genres).to eq(["electronic"])
|
3688
|
+
end
|
3689
|
+
|
3690
|
+
it "removes last element in array" do
|
3691
|
+
context.update_all("$pop" => { genres: 1 })
|
3692
|
+
expect(depeche_mode.reload.genres).to eq(["pop"])
|
3693
|
+
end
|
3694
|
+
end
|
3695
|
+
|
3696
|
+
context "when operation is $pullAll" do
|
3697
|
+
|
3698
|
+
before do
|
3699
|
+
depeche_mode.update_attribute(:genres, ["pop", "electronic", "dance", "pop" ])
|
3700
|
+
new_order.update_attribute(:genres, ["electronic", "pop", "electronic", "dance"])
|
3701
|
+
context.update_all("$pullAll" => { genres: ["pop", "electronic"] })
|
3702
|
+
end
|
3703
|
+
|
3704
|
+
it "updates the first matching document" do
|
3705
|
+
expect(depeche_mode.reload.genres).to eq(["dance"])
|
3706
|
+
end
|
3707
|
+
|
3708
|
+
it "updates the last matching document" do
|
3709
|
+
expect(new_order.reload.genres).to eq(["dance"])
|
3710
|
+
end
|
3711
|
+
end
|
3643
3712
|
end
|
3644
3713
|
|
3645
3714
|
context 'when using aliased field names' do
|
@@ -3659,15 +3728,15 @@ describe Mongoid::Contextual::Mongo do
|
|
3659
3728
|
context "when the attributes must be mongoized" do
|
3660
3729
|
|
3661
3730
|
before do
|
3662
|
-
context.update_all("$set" => {
|
3731
|
+
context.update_all("$set" => { location: LatLng.new(52.30, 13.25) })
|
3663
3732
|
end
|
3664
3733
|
|
3665
3734
|
it "updates the first matching document" do
|
3666
|
-
expect(depeche_mode.reload.
|
3735
|
+
expect(depeche_mode.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3667
3736
|
end
|
3668
3737
|
|
3669
3738
|
it "updates the last matching document" do
|
3670
|
-
expect(new_order.reload.
|
3739
|
+
expect(new_order.reload.location).to eq(LatLng.new(52.30, 13.25))
|
3671
3740
|
end
|
3672
3741
|
end
|
3673
3742
|
end
|
data/spec/mongoid/fields_spec.rb
CHANGED
@@ -1871,12 +1871,12 @@ describe Mongoid::Fields do
|
|
1871
1871
|
|
1872
1872
|
context 'given nil' do
|
1873
1873
|
subject { Person.database_field_name(nil) }
|
1874
|
-
it { is_expected.to eq
|
1874
|
+
it { is_expected.to eq '' }
|
1875
1875
|
end
|
1876
1876
|
|
1877
1877
|
context 'given an empty String' do
|
1878
1878
|
subject { Person.database_field_name('') }
|
1879
|
-
it { is_expected.to eq
|
1879
|
+
it { is_expected.to eq '' }
|
1880
1880
|
end
|
1881
1881
|
|
1882
1882
|
context 'given a String' do
|
@@ -2594,4 +2594,35 @@ describe Mongoid::Interceptable do
|
|
2594
2594
|
end
|
2595
2595
|
end
|
2596
2596
|
end
|
2597
|
+
|
2598
|
+
context "when around callbacks for embedded children are enabled" do
|
2599
|
+
config_override :around_callbacks_for_embeds, true
|
2600
|
+
|
2601
|
+
context "when around callback is defined without a yield" do
|
2602
|
+
class Mother
|
2603
|
+
include Mongoid::Document
|
2604
|
+
embeds_many :daughters, cascade_callbacks: true
|
2605
|
+
end
|
2606
|
+
|
2607
|
+
class Daughter
|
2608
|
+
include Mongoid::Document
|
2609
|
+
embedded_in :mother
|
2610
|
+
around_save :log_callback
|
2611
|
+
|
2612
|
+
private
|
2613
|
+
|
2614
|
+
def log_callback
|
2615
|
+
logger.debug('callback invoked')
|
2616
|
+
end
|
2617
|
+
end
|
2618
|
+
|
2619
|
+
let(:mom) { Mother.create(daughters: [ Daughter.new, Daughter.new ]) }
|
2620
|
+
|
2621
|
+
it "raises an InvalidAroundCallback error" do
|
2622
|
+
expect do
|
2623
|
+
mom.save
|
2624
|
+
end.to raise_error(Mongoid::Errors::InvalidAroundCallback)
|
2625
|
+
end
|
2626
|
+
end
|
2627
|
+
end
|
2597
2628
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'support/feature_sandbox'
|
5
|
+
|
6
|
+
MONGOID_MODEL_RESOLVER_KEY__ = :__separate_instance_spec_key
|
7
|
+
Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, MONGOID_MODEL_RESOLVER_KEY__
|
8
|
+
|
9
|
+
def quarantine(context, &block)
|
10
|
+
state = {}
|
11
|
+
|
12
|
+
context.before(:context) do
|
13
|
+
state[:quarantine] = FeatureSandbox.start_quarantine
|
14
|
+
block&.call
|
15
|
+
end
|
16
|
+
|
17
|
+
context.after(:context) do
|
18
|
+
FeatureSandbox.end_quarantine(state[:quarantine])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Mongoid::ModelResolver do
|
23
|
+
shared_examples 'a resolver' do |**kwargs|
|
24
|
+
it 'includes the class name when asked for all keys of the given model' do
|
25
|
+
expect(resolver.keys_for(model_class.new)).to include(model_class.name)
|
26
|
+
end
|
27
|
+
|
28
|
+
if kwargs[:with_aliases].nil?
|
29
|
+
it 'uses the class name as the default key for the given model' do
|
30
|
+
expect(resolver.default_key_for(model_class.new)).to eq model_class.name
|
31
|
+
end
|
32
|
+
elsif kwargs[:with_aliases].is_a?(Array)
|
33
|
+
it 'uses the first alias as the default key for the given model' do
|
34
|
+
expect(resolver.default_key_for(model_class.new)).to eq kwargs[:with_aliases].first
|
35
|
+
end
|
36
|
+
else
|
37
|
+
it 'uses the alias as the default key for the given model' do
|
38
|
+
expect(resolver.default_key_for(model_class.new)).to eq kwargs[:with_aliases]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns the model class when queried with the class name' do
|
43
|
+
expect(resolver.model_for(model_class.name)).to eq model_class
|
44
|
+
end
|
45
|
+
|
46
|
+
Array(kwargs[:with_aliases]).each do |model_alias|
|
47
|
+
it "includes the alias #{model_alias.inspect} when asked for all keys of the given model" do
|
48
|
+
expect(resolver.keys_for(model_class.new)).to include(model_alias)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns the model class when queried with #{model_alias.inspect}" do
|
52
|
+
expect(resolver.model_for(model_alias)).to eq model_class
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when using the default instance' do
|
58
|
+
let(:resolver) { described_class.instance }
|
59
|
+
|
60
|
+
context 'when an alias is not specified' do
|
61
|
+
quarantine(self) do
|
62
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
63
|
+
module Mongoid; module Specs; module DefaultInstance
|
64
|
+
class Vanilla; include Mongoid::Document; end
|
65
|
+
end; end; end
|
66
|
+
RUBY
|
67
|
+
end
|
68
|
+
|
69
|
+
let(:model_class) { Mongoid::Specs::DefaultInstance::Vanilla }
|
70
|
+
|
71
|
+
it_behaves_like 'a resolver'
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when one alias is specified' do
|
75
|
+
quarantine(self) do
|
76
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
77
|
+
module Mongoid; module Specs; module DefaultInstance
|
78
|
+
class Aliased
|
79
|
+
include Mongoid::Document
|
80
|
+
identify_as 'aliased'
|
81
|
+
end
|
82
|
+
end; end; end
|
83
|
+
RUBY
|
84
|
+
end
|
85
|
+
|
86
|
+
let(:model_class) { Mongoid::Specs::DefaultInstance::Aliased }
|
87
|
+
|
88
|
+
it_behaves_like 'a resolver', with_aliases: 'aliased'
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when multiple aliases are specified' do
|
92
|
+
quarantine(self) do
|
93
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
94
|
+
module Mongoid; module Specs; module DefaultInstance
|
95
|
+
class AliasedMultiple
|
96
|
+
include Mongoid::Document
|
97
|
+
identify_as 'aliased', 'alias2', 'alias3'
|
98
|
+
end
|
99
|
+
end; end; end
|
100
|
+
RUBY
|
101
|
+
end
|
102
|
+
|
103
|
+
let(:model_class) { Mongoid::Specs::DefaultInstance::AliasedMultiple }
|
104
|
+
|
105
|
+
it_behaves_like 'a resolver', with_aliases: %w[ aliased alias2 alias3 ]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'when using a separate instance' do
|
110
|
+
let(:resolver) { described_class.resolver(MONGOID_MODEL_RESOLVER_KEY__) }
|
111
|
+
|
112
|
+
it 'does not refer to the default instance' do
|
113
|
+
expect(resolver).not_to eq described_class.instance
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when an alias is not specified' do
|
117
|
+
quarantine(self) do
|
118
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
119
|
+
module Mongoid; module Specs; module SeparateInstance
|
120
|
+
class Vanilla
|
121
|
+
include Mongoid::Document
|
122
|
+
identify_as resolver: MONGOID_MODEL_RESOLVER_KEY__
|
123
|
+
end
|
124
|
+
end; end; end
|
125
|
+
RUBY
|
126
|
+
end
|
127
|
+
|
128
|
+
let(:model_class) { Mongoid::Specs::SeparateInstance::Vanilla }
|
129
|
+
|
130
|
+
it_behaves_like 'a resolver'
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'when one alias is specified' do
|
134
|
+
quarantine(self) do
|
135
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
136
|
+
module Mongoid; module Specs; module SeparateInstance
|
137
|
+
class Aliased
|
138
|
+
include Mongoid::Document
|
139
|
+
identify_as 'aliased', resolver: MONGOID_MODEL_RESOLVER_KEY__
|
140
|
+
end
|
141
|
+
end; end; end
|
142
|
+
RUBY
|
143
|
+
end
|
144
|
+
|
145
|
+
let(:model_class) { Mongoid::Specs::SeparateInstance::Aliased }
|
146
|
+
|
147
|
+
it_behaves_like 'a resolver', with_aliases: 'aliased'
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when multiple aliases are specified' do
|
151
|
+
quarantine(self) do
|
152
|
+
Object.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
153
|
+
module Mongoid; module Specs; module SeparateInstance
|
154
|
+
class AliasedMultiple
|
155
|
+
include Mongoid::Document
|
156
|
+
identify_as 'aliased', 'alias2', 'alias3', resolver: MONGOID_MODEL_RESOLVER_KEY__
|
157
|
+
end
|
158
|
+
end; end; end
|
159
|
+
RUBY
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:model_class) { Mongoid::Specs::SeparateInstance::AliasedMultiple }
|
163
|
+
|
164
|
+
it_behaves_like 'a resolver', with_aliases: %w[ aliased alias2 alias3 ]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
# @note This test ensures that we do not inadvertently introduce new monkey patches
|
6
6
|
# to Mongoid. Existing monkey patch methods which are marked with +Mongoid.deprecated+
|
7
7
|
# are excluded from this test.
|
8
|
-
RSpec.describe('Do not add monkey patches') do
|
8
|
+
RSpec.describe('Do not add monkey patches') do
|
9
9
|
classes = [
|
10
10
|
Object,
|
11
11
|
Array,
|
@@ -206,12 +206,25 @@ describe Mongoid::PersistenceContext do
|
|
206
206
|
|
207
207
|
context 'when the options are valid extra options' do
|
208
208
|
|
209
|
-
|
210
|
-
|
209
|
+
context 'collection' do
|
210
|
+
|
211
|
+
let(:options) do
|
212
|
+
{ collection: 'other' }
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'sets the options on the persistence context object' do
|
216
|
+
expect(persistence_context.collection_name).to eq(options[:collection].to_sym)
|
217
|
+
end
|
211
218
|
end
|
212
219
|
|
213
|
-
|
214
|
-
|
220
|
+
context 'collection_options' do
|
221
|
+
let(:options) do
|
222
|
+
{ collection_options: { capped: true } }
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'does not propagate to client options' do
|
226
|
+
expect(persistence_context.send(:client_options).key?(:collection_options)).to eq(false)
|
227
|
+
end
|
215
228
|
end
|
216
229
|
end
|
217
230
|
|