mongoid 9.0.2 → 9.0.4

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mongoid/attributes/readonly.rb +8 -3
  3. data/lib/mongoid/clients/options.rb +14 -1
  4. data/lib/mongoid/clients/sessions.rb +1 -0
  5. data/lib/mongoid/criteria/queryable/selectable.rb +1 -1
  6. data/lib/mongoid/equality.rb +1 -0
  7. data/lib/mongoid/loadable.rb +72 -8
  8. data/lib/mongoid/matcher.rb +15 -1
  9. data/lib/mongoid/persistence_context.rb +14 -9
  10. data/lib/mongoid/railties/controller_runtime.rb +2 -2
  11. data/lib/mongoid/serializable.rb +7 -7
  12. data/lib/mongoid/threaded.rb +96 -28
  13. data/lib/mongoid/timestamps/timeless.rb +4 -1
  14. data/lib/mongoid/touchable.rb +1 -1
  15. data/lib/mongoid/traversable.rb +25 -2
  16. data/lib/mongoid/validatable/associated.rb +5 -2
  17. data/lib/mongoid/version.rb +1 -1
  18. data/spec/integration/active_job_spec.rb +24 -20
  19. data/spec/integration/app_spec.rb +9 -1
  20. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +4 -0
  21. data/spec/mongoid/attributes/readonly_spec.rb +19 -0
  22. data/spec/mongoid/clients/options_spec.rb +127 -2
  23. data/spec/mongoid/criteria/queryable/selectable_spec.rb +29 -0
  24. data/spec/mongoid/equality_spec.rb +6 -0
  25. data/spec/mongoid/interceptable_spec.rb +12 -0
  26. data/spec/mongoid/interceptable_spec_models.rb +12 -0
  27. data/spec/mongoid/loadable_spec.rb +86 -0
  28. data/spec/mongoid/persistence_context_spec.rb +39 -0
  29. data/spec/mongoid/railties/bson_object_id_serializer_spec.rb +18 -12
  30. data/spec/mongoid/threaded_spec.rb +24 -5
  31. data/spec/mongoid/validatable/associated_spec.rb +14 -4
  32. data/spec/rails/controller_extension/controller_runtime_spec.rb +14 -14
  33. metadata +7 -8
@@ -70,13 +70,16 @@ module Mongoid
70
70
  # Now, treating the target as an array, look at each element
71
71
  # and see if it is valid, but only if it has already been
72
72
  # persisted, or changed, and hasn't been flagged for destroy.
73
- list.all? do |value|
73
+ #
74
+ # use map.all? instead of just all?, because all? will do short-circuit
75
+ # evaluation and terminate on the first failed validation.
76
+ list.map do |value|
74
77
  if value && !value.flagged_for_destroy? && (!value.persisted? || value.changed?)
75
78
  value.validated? ? true : value.valid?
76
79
  else
77
80
  true
78
81
  end
79
- end
82
+ end.all?
80
83
  end
81
84
 
82
85
  document.errors.add(attribute, :invalid) unless valid
@@ -2,5 +2,5 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  module Mongoid
5
- VERSION = "9.0.2"
5
+ VERSION = "9.0.4"
6
6
  end
@@ -2,31 +2,35 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  require 'spec_helper'
5
- require 'active_job'
6
- require 'mongoid/railties/bson_object_id_serializer'
5
+ begin
6
+ require 'active_job'
7
+ require 'mongoid/railties/bson_object_id_serializer'
7
8
 
8
- describe 'ActiveJob Serialization' do
9
- skip unless defined?(ActiveJob)
9
+ describe 'ActiveJob Serialization' do
10
+ skip unless defined?(ActiveJob)
10
11
 
11
- class TestBsonObjectIdSerializerJob < ActiveJob::Base
12
- def perform(*args)
13
- args
12
+ class TestBsonObjectIdSerializerJob < ActiveJob::Base
13
+ def perform(*args)
14
+ args
15
+ end
14
16
  end
15
- end
16
17
 
17
- let(:band) do
18
- Band.create!
19
- end
18
+ let(:band) do
19
+ Band.create!
20
+ end
20
21
 
21
- before do
22
- ActiveJob::Serializers.add_serializers(
23
- [::Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer]
24
- )
25
- end
22
+ before do
23
+ ActiveJob::Serializers.add_serializers(
24
+ [::Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer]
25
+ )
26
+ end
26
27
 
27
- it 'serializes and deserializes BSON::ObjectId' do
28
- expect do
29
- TestBsonObjectIdSerializerJob.perform_later(band.id)
30
- end.not_to raise_error
28
+ it 'serializes and deserializes BSON::ObjectId' do
29
+ expect do
30
+ TestBsonObjectIdSerializerJob.perform_later(band.id)
31
+ end.not_to raise_error
32
+ end
31
33
  end
34
+ rescue LoadError
35
+ RSpec.context.skip 'This test requires active_job'
32
36
  end
@@ -36,6 +36,8 @@ describe 'Mongoid application tests' do
36
36
  context 'demo application' do
37
37
  context 'sinatra' do
38
38
  it 'runs' do
39
+ skip 'https://jira.mongodb.org/browse/MONGOID-5826'
40
+
39
41
  clone_application(
40
42
  'https://github.com/mongoid/mongoid-demo',
41
43
  subdir: 'sinatra-minimal',
@@ -55,6 +57,8 @@ describe 'Mongoid application tests' do
55
57
 
56
58
  context 'rails-api' do
57
59
  it 'runs' do
60
+ skip 'https://jira.mongodb.org/browse/MONGOID-5826'
61
+
58
62
  clone_application(
59
63
  'https://github.com/mongoid/mongoid-demo',
60
64
  subdir: 'rails-api',
@@ -172,7 +176,7 @@ describe 'Mongoid application tests' do
172
176
  if (rails_version = SpecConfig.instance.rails_version) == 'master'
173
177
  else
174
178
  check_call(%w(gem list))
175
- check_call(%w(gem install rails --no-document -v) + ["~> #{rails_version}.0"])
179
+ check_call(%w(gem install rails --no-document --force -v) + ["~> #{rails_version}.0"])
176
180
  end
177
181
  end
178
182
 
@@ -319,6 +323,10 @@ describe 'Mongoid application tests' do
319
323
  end
320
324
 
321
325
  def adjust_rails_defaults(rails_version: SpecConfig.instance.rails_version)
326
+ if !rails_version.match?(/^\d+\.\d+$/)
327
+ # This must be pre-release version, we trim it
328
+ rails_version = rails_version.split('.')[0..1].join('.')
329
+ end
322
330
  if File.exist?('config/application.rb')
323
331
  lines = IO.readlines('config/application.rb')
324
332
  lines.each do |line|
@@ -751,6 +751,10 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
751
751
  person.save!
752
752
  end
753
753
 
754
+ # NOTE: there as a bad interdependency here, with the auto_save_spec.rb
755
+ # file. If auto_save_spec.rb runs before this, the following specs fail
756
+ # with "undefined method `nullify' for an instance of Person".
757
+
754
758
  context "when parent exists" do
755
759
 
756
760
  context "when child is destroyed" do
@@ -266,7 +266,26 @@ describe Mongoid::Attributes::Readonly do
266
266
  expect(child.mother).to be_nil
267
267
  end
268
268
  end
269
+ end
270
+
271
+ context "when a subclass inherits readonly fields" do
272
+ let(:attributes) do
273
+ [:title, :terms]
274
+ end
275
+
276
+ before do
277
+ class OldPerson < Person
278
+ attr_readonly :age
279
+ end
280
+ end
269
281
 
282
+ it "ensures subclass inherits the readonly attributes from parent" do
283
+ expect(OldPerson.readonly_attributes.to_a).to include("title","terms")
284
+ end
285
+
286
+ it "ensures subclass does not modify parent's readonly attributes" do
287
+ expect(Person.readonly_attributes.to_a).not_to include("age")
288
+ end
270
289
  end
271
290
  end
272
291
  end
@@ -27,7 +27,7 @@ describe Mongoid::Clients::Options, retry: 3 do
27
27
  let(:options) { { database: 'other' } }
28
28
 
29
29
  it 'sets the options on the client' do
30
- expect(persistence_context.client.options['database']).to eq(options[:database])
30
+ expect(persistence_context.client.options['database'].to_s).to eq(options[:database].to_s)
31
31
  end
32
32
 
33
33
  it 'does not set the options on class level' do
@@ -319,7 +319,7 @@ describe Mongoid::Clients::Options, retry: 3 do
319
319
  end
320
320
 
321
321
  it 'sets the options on the client' do
322
- expect(persistence_context.client.options['database']).to eq(options[:database])
322
+ expect(persistence_context.client.options['database'].to_s).to eq(options[:database].to_s)
323
323
  end
324
324
 
325
325
  it 'does not set the options on instance level' do
@@ -522,4 +522,129 @@ describe Mongoid::Clients::Options, retry: 3 do
522
522
  end
523
523
  end
524
524
  end
525
+
526
+ context 'with global overrides' do
527
+ let(:default_subscriber) do
528
+ Mrss::EventSubscriber.new
529
+ end
530
+
531
+ let(:override_subscriber) do
532
+ Mrss::EventSubscriber.new
533
+ end
534
+
535
+ context 'when global client is overridden' do
536
+ before do
537
+ Mongoid.clients['override_client'] = { hosts: SpecConfig.instance.addresses, database: 'default_override_database' }
538
+ Mongoid.override_client('override_client')
539
+ Mongoid.client(:default).subscribe(Mongo::Monitoring::COMMAND, default_subscriber)
540
+ Mongoid.client('override_client').subscribe(Mongo::Monitoring::COMMAND, override_subscriber)
541
+ end
542
+
543
+ after do
544
+ Mongoid.client(:default).unsubscribe(Mongo::Monitoring::COMMAND, default_subscriber)
545
+ Mongoid.client('override_client').unsubscribe(Mongo::Monitoring::COMMAND, override_subscriber)
546
+ Mongoid.override_client(nil)
547
+ Mongoid.clients['override_client'] = nil
548
+ end
549
+
550
+ it 'uses the overridden client for create' do
551
+ Minim.create!
552
+
553
+ expect(override_subscriber.single_command_started_event('insert').database_name).to eq('default_override_database')
554
+ expect(default_subscriber.command_started_events('insert')).to be_empty
555
+ end
556
+
557
+ it 'uses the overridden client for queries' do
558
+ Minim.where(name: 'Dmitry').to_a
559
+
560
+ expect(override_subscriber.single_command_started_event('find').database_name).to eq('default_override_database')
561
+ expect(default_subscriber.command_started_events('find')).to be_empty
562
+ end
563
+
564
+ context 'when the client is set on the model level' do
565
+ let(:model_level_subscriber) do
566
+ Mrss::EventSubscriber.new
567
+ end
568
+
569
+ around(:example) do |example|
570
+ opts = Minim.storage_options
571
+ Minim.storage_options = Minim.storage_options.merge( { client: 'model_level_client' } )
572
+ Mongoid.clients['model_level_client'] = { hosts: SpecConfig.instance.addresses, database: 'model_level_database' }
573
+ Mongoid.client('model_level_client').subscribe(Mongo::Monitoring::COMMAND, override_subscriber)
574
+ example.run
575
+ Mongoid.client('model_level_client').unsubscribe(Mongo::Monitoring::COMMAND, override_subscriber)
576
+ Mongoid.clients['model_level_client'] = nil
577
+ Minim.storage_options = opts
578
+ end
579
+
580
+ # This behaviour is consistent with 8.x
581
+ it 'uses the overridden client for create' do
582
+ Minim.create!
583
+
584
+ expect(override_subscriber.single_command_started_event('insert').database_name).to eq('default_override_database')
585
+ expect(default_subscriber.command_started_events('insert')).to be_empty
586
+ expect(model_level_subscriber.command_started_events('insert')).to be_empty
587
+ end
588
+
589
+ # This behaviour is consistent with 8.x
590
+ it 'uses the overridden client for queries' do
591
+ Minim.where(name: 'Dmitry').to_a
592
+
593
+ expect(override_subscriber.single_command_started_event('find').database_name).to eq('default_override_database')
594
+ expect(default_subscriber.command_started_events('find')).to be_empty
595
+ expect(model_level_subscriber.command_started_events('find')).to be_empty
596
+ end
597
+ end
598
+ end
599
+
600
+ context 'when global database is overridden' do
601
+ before do
602
+ Mongoid.override_database('override_database')
603
+ Mongoid.client(:default).subscribe(Mongo::Monitoring::COMMAND, default_subscriber)
604
+ end
605
+
606
+ after do
607
+ Mongoid.client(:default).unsubscribe(Mongo::Monitoring::COMMAND, default_subscriber)
608
+ Mongoid.override_database(nil)
609
+ end
610
+
611
+ it 'uses the overridden database for create' do
612
+ Minim.create!
613
+
614
+ expect(default_subscriber.single_command_started_event('insert').database_name).to eq('override_database')
615
+ end
616
+
617
+ it 'uses the overridden database for queries' do
618
+ Minim.where(name: 'Dmitry').to_a
619
+
620
+ expect(default_subscriber.single_command_started_event('find').database_name).to eq('override_database')
621
+ end
622
+
623
+ context 'when the database is set on the model level' do
624
+ around(:example) do |example|
625
+ opts = Minim.storage_options
626
+ Minim.storage_options = Minim.storage_options.merge( { database: 'model_level_database' } )
627
+ Mongoid.clients['model_level_client'] = { hosts: SpecConfig.instance.addresses, database: 'model_level_database' }
628
+ Mongoid.client(:default).subscribe(Mongo::Monitoring::COMMAND, default_subscriber)
629
+ example.run
630
+ Mongoid.client(:default).unsubscribe(Mongo::Monitoring::COMMAND, default_subscriber)
631
+ Mongoid.clients['model_level_client'] = nil
632
+ Minim.storage_options = opts
633
+ end
634
+
635
+ # This behaviour is consistent with 8.x
636
+ it 'uses the overridden database for create' do
637
+ Minim.create!
638
+
639
+ expect(default_subscriber.single_command_started_event('insert').database_name).to eq('override_database')
640
+ end
641
+
642
+ it 'uses the overridden database for queries' do
643
+ Minim.where(name: 'Dmitry').to_a
644
+
645
+ expect(default_subscriber.single_command_started_event('find').database_name).to eq('override_database')
646
+ end
647
+ end
648
+ end
649
+ end
525
650
  end
@@ -1939,6 +1939,35 @@ describe Mongoid::Criteria::Queryable::Selectable do
1939
1939
  end
1940
1940
  end
1941
1941
 
1942
+ describe "#not" do
1943
+ context "when negating a criterion" do
1944
+ let(:selection) do
1945
+ query.not(field: /value/)
1946
+ end
1947
+
1948
+ it "adds the $not selector" do
1949
+ expect(selection.selector).to eq({
1950
+ "field" => { "$not" => /value/ }
1951
+ })
1952
+ end
1953
+
1954
+ it "returns a cloned query" do
1955
+ expect(selection).to_not equal(query)
1956
+ end
1957
+
1958
+ context "when toggling negation state" do
1959
+ it "negates the negating value" do
1960
+ expect(query.negating).to be_nil
1961
+ negated_query = query.not
1962
+ expect(negated_query.negating).to be true
1963
+ double_negated_query = negated_query.not
1964
+ expect(double_negated_query.negating).to be false
1965
+ end
1966
+ end
1967
+ end
1968
+ end
1969
+
1970
+
1942
1971
  describe Symbol do
1943
1972
 
1944
1973
  describe "#all" do
@@ -189,6 +189,12 @@ describe Mongoid::Equality do
189
189
  it "compares based on the document id" do
190
190
  expect(first <=> second).to eq(-1)
191
191
  end
192
+
193
+ it "doesn't break if one isn't a document" do
194
+ expect do
195
+ first <=> "Foo"
196
+ end.to_not raise_error
197
+ end
192
198
  end
193
199
 
194
200
  describe "#eql?" do
@@ -1789,6 +1789,12 @@ describe Mongoid::Interceptable do
1789
1789
  context 'with around callbacks' do
1790
1790
  config_override :around_callbacks_for_embeds, true
1791
1791
 
1792
+ after do
1793
+ Mongoid::Threaded.stack('interceptable').clear
1794
+ end
1795
+
1796
+ let(:stack) { Mongoid::Threaded.stack('interceptable') }
1797
+
1792
1798
  let(:expected) do
1793
1799
  [
1794
1800
  [InterceptableSpec::CbCascadedChild, :before_validation],
@@ -1824,6 +1830,12 @@ describe Mongoid::Interceptable do
1824
1830
  parent.save!
1825
1831
  expect(registry.calls).to eq expected
1826
1832
  end
1833
+
1834
+ it 'shows that cascaded callbacks can access Mongoid state' do
1835
+ expect(stack).to be_empty
1836
+ parent.save!
1837
+ expect(stack).not_to be_empty
1838
+ end
1827
1839
  end
1828
1840
 
1829
1841
  context 'without around callbacks' do
@@ -224,7 +224,19 @@ module InterceptableSpec
224
224
 
225
225
  attr_accessor :callback_registry
226
226
 
227
+ before_save :test_mongoid_state
228
+
227
229
  include CallbackTracking
230
+
231
+ private
232
+
233
+ # Helps test that cascading child callbacks have access to the Mongoid
234
+ # state objects; if the implementation uses fiber-local (instead of truly
235
+ # thread-local) variables, the related tests will fail because the
236
+ # cascading child callbacks use fibers to linearize the recursion.
237
+ def test_mongoid_state
238
+ Mongoid::Threaded.stack('interceptable').push(self)
239
+ end
228
240
  end
229
241
  end
230
242
 
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Mongoid::Loadable do
6
+ let(:lib_dir) { Pathname.new('../../lib').realpath(__dir__) }
7
+
8
+ shared_context 'with ignore_patterns' do
9
+ around do |example|
10
+ saved = Mongoid.ignore_patterns
11
+ Mongoid.ignore_patterns = ignore_patterns
12
+ example.run
13
+ ensure
14
+ Mongoid.ignore_patterns = saved
15
+ end
16
+ end
17
+
18
+ describe '#ignore_patterns' do
19
+ context 'when not explicitly set' do
20
+ it 'equals the default list of ignore patterns' do
21
+ expect(Mongoid.ignore_patterns).to eq Mongoid::Loadable::DEFAULT_IGNORE_PATTERNS
22
+ end
23
+ end
24
+
25
+ context 'when explicitly set' do
26
+ include_context 'with ignore_patterns'
27
+
28
+ let(:ignore_patterns) { %w[ pattern1 pattern2 ] }
29
+
30
+ it 'equals the list of specified patterns' do
31
+ expect(Mongoid.ignore_patterns).to eq ignore_patterns
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '#files_under_path' do
37
+ let(:results) { Mongoid.files_under_path(lib_dir) }
38
+
39
+ include_context 'with ignore_patterns'
40
+
41
+ context 'when ignore_patterns is empty' do
42
+ let(:ignore_patterns) { [] }
43
+
44
+ it 'returns all ruby files' do
45
+ expect(results.length).to be > 10 # should be a bunch of them
46
+ expect(results).to include('rails/mongoid')
47
+ end
48
+ end
49
+
50
+ context 'when ignore_patterns is not empty' do
51
+ let(:ignore_patterns) { %w[ */rails/* ] }
52
+
53
+ it 'omits the ignored paths' do
54
+ expect(results.length).to be > 10 # should be a bunch of them
55
+ expect(results).not_to include('rails/mongoid')
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#files_under_paths' do
61
+ let(:paths) { [ lib_dir.join('mongoid'), lib_dir.join('rails') ] }
62
+ let(:results) { Mongoid.files_under_paths(paths) }
63
+
64
+ include_context 'with ignore_patterns'
65
+
66
+ context 'when ignore_patterns is empty' do
67
+ let(:ignore_patterns) { [] }
68
+
69
+ it 'returns all ruby files' do
70
+ expect(results.length).to be > 10 # should be a bunch
71
+ expect(results).to include('generators/mongoid/model/model_generator')
72
+ expect(results).to include('fields/encrypted')
73
+ end
74
+ end
75
+
76
+ context 'when ignore_patterns is not empty' do
77
+ let(:ignore_patterns) { %w[ */model/* */fields/* ] }
78
+
79
+ it 'returns all ruby files' do
80
+ expect(results.length).to be > 10 # should be a bunch
81
+ expect(results).not_to include('generators/mongoid/model/model_generator')
82
+ expect(results).not_to include('fields/encrypted')
83
+ end
84
+ end
85
+ end
86
+ end
@@ -536,6 +536,20 @@ describe Mongoid::PersistenceContext do
536
536
  end
537
537
  end
538
538
  end
539
+
540
+ context 'when the database is specified as a proc' do
541
+ let(:options) { { database: ->{ 'other' } } }
542
+
543
+ after { persistence_context.client.close }
544
+
545
+ it 'evaluates the proc' do
546
+ expect(persistence_context.database_name).to eq(:other)
547
+ end
548
+
549
+ it 'does not pass the proc to the client' do
550
+ expect(persistence_context.client.database.name).to eq('other')
551
+ end
552
+ end
539
553
  end
540
554
 
541
555
  describe '#client' do
@@ -570,6 +584,14 @@ describe Mongoid::PersistenceContext do
570
584
  expect(persistence_context.client).to eq(Mongoid::Clients.with_name(:alternative))
571
585
  end
572
586
 
587
+ context 'when the client option is a proc' do
588
+ let(:options) { { client: -> { :alternative } } }
589
+
590
+ it 'evaluates the proc' do
591
+ expect(persistence_context.client).to eq(Mongoid::Clients.with_name(:alternative))
592
+ end
593
+ end
594
+
573
595
  context 'when there is a client override' do
574
596
  persistence_context_override :client, :other
575
597
 
@@ -608,6 +630,23 @@ describe Mongoid::PersistenceContext do
608
630
  end
609
631
  end
610
632
 
633
+ context 'when the client is set as a proc in the storage options' do
634
+ let(:options) { {} }
635
+
636
+ before do
637
+ Band.store_in client: ->{ :alternative }
638
+ end
639
+
640
+ after do
641
+ persistence_context.client.close
642
+ Band.store_in client: nil
643
+ end
644
+
645
+ it 'uses the client option' do
646
+ expect(persistence_context.client).to eq(Mongoid::Clients.with_name(:alternative))
647
+ end
648
+ end
649
+
611
650
  context 'when there is no client option set' do
612
651
 
613
652
  let(:options) do
@@ -2,23 +2,29 @@
2
2
  # rubocop:todo all
3
3
 
4
4
  require 'spec_helper'
5
- require 'active_job'
6
- require 'mongoid/railties/bson_object_id_serializer'
7
5
 
8
- describe 'Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer' do
6
+ begin
7
+ require 'active_job'
8
+ require 'mongoid/railties/bson_object_id_serializer'
9
9
 
10
- let(:serializer) { Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer.instance }
11
- let(:object_id) { BSON::ObjectId.new }
12
10
 
13
- describe '#serialize' do
14
- it 'serializes BSON::ObjectId' do
15
- expect(serializer.serialize(object_id)).to be_a(String)
11
+ describe 'Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer' do
12
+
13
+ let(:serializer) { Mongoid::Railties::ActiveJobSerializers::BsonObjectIdSerializer.instance }
14
+ let(:object_id) { BSON::ObjectId.new }
15
+
16
+ describe '#serialize' do
17
+ it 'serializes BSON::ObjectId' do
18
+ expect(serializer.serialize(object_id)).to be_a(String)
19
+ end
16
20
  end
17
- end
18
21
 
19
- describe '#deserialize' do
20
- it 'deserializes BSON::ObjectId' do
21
- expect(serializer.deserialize(serializer.serialize(object_id))).to eq(object_id)
22
+ describe '#deserialize' do
23
+ it 'deserializes BSON::ObjectId' do
24
+ expect(serializer.deserialize(serializer.serialize(object_id))).to eq(object_id)
25
+ end
22
26
  end
23
27
  end
28
+ rescue LoadError
29
+ RSpec.context.skip 'This test requires active_job'
24
30
  end
@@ -36,11 +36,11 @@ describe Mongoid::Threaded do
36
36
  context "when the stack has elements" do
37
37
 
38
38
  before do
39
- Thread.current["[mongoid]:load-stack"] = [ true ]
39
+ described_class.stack('load').push(true)
40
40
  end
41
41
 
42
42
  after do
43
- Thread.current["[mongoid]:load-stack"] = []
43
+ described_class.stack('load').clear
44
44
  end
45
45
 
46
46
  it "returns true" do
@@ -51,7 +51,7 @@ describe Mongoid::Threaded do
51
51
  context "when the stack has no elements" do
52
52
 
53
53
  before do
54
- Thread.current["[mongoid]:load-stack"] = []
54
+ described_class.stack('load').clear
55
55
  end
56
56
 
57
57
  it "returns false" do
@@ -76,7 +76,7 @@ describe Mongoid::Threaded do
76
76
  context "when a stack has been initialized" do
77
77
 
78
78
  before do
79
- Thread.current["[mongoid]:load-stack"] = [ true ]
79
+ described_class.stack('load').push(true)
80
80
  end
81
81
 
82
82
  let(:loading) do
@@ -84,7 +84,7 @@ describe Mongoid::Threaded do
84
84
  end
85
85
 
86
86
  after do
87
- Thread.current["[mongoid]:load-stack"] = []
87
+ described_class.stack('load').clear
88
88
  end
89
89
 
90
90
  it "returns the stack" do
@@ -341,4 +341,23 @@ describe Mongoid::Threaded do
341
341
  end
342
342
  end
343
343
  end
344
+
345
+ describe '#clear_modified_documents' do
346
+ let(:session) do
347
+ double(Mongo::Session).tap do |session|
348
+ allow(session).to receive(:in_transaction?).and_return(true)
349
+ end
350
+ end
351
+
352
+ context 'when there are modified documents' do
353
+ before do
354
+ described_class.add_modified_document(session, Minim.new)
355
+ described_class.clear_modified_documents(session)
356
+ end
357
+
358
+ it 'removes the documents and keys' do
359
+ expect(described_class.modified_documents).to be_empty
360
+ end
361
+ end
362
+ end
344
363
  end