mongoid 7.1.0.rc0 → 7.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +6 -6
  5. data/LICENSE +1 -1
  6. data/README.md +5 -5
  7. data/Rakefile +14 -0
  8. data/lib/config/locales/en.yml +5 -5
  9. data/lib/mongoid.rb +3 -2
  10. data/lib/mongoid/association/accessors.rb +37 -2
  11. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  12. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  13. data/lib/mongoid/association/many.rb +3 -2
  14. data/lib/mongoid/association/proxy.rb +6 -4
  15. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -1
  16. data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
  17. data/lib/mongoid/association/referenced/eager.rb +29 -9
  18. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -22
  19. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -2
  20. data/lib/mongoid/atomic.rb +13 -3
  21. data/lib/mongoid/attributes.rb +28 -20
  22. data/lib/mongoid/clients/factory.rb +2 -2
  23. data/lib/mongoid/clients/options.rb +8 -8
  24. data/lib/mongoid/clients/sessions.rb +20 -4
  25. data/lib/mongoid/clients/storage_options.rb +5 -5
  26. data/lib/mongoid/config.rb +42 -12
  27. data/lib/mongoid/config/options.rb +5 -2
  28. data/lib/mongoid/contextual.rb +5 -4
  29. data/lib/mongoid/contextual/geo_near.rb +3 -2
  30. data/lib/mongoid/contextual/map_reduce.rb +3 -2
  31. data/lib/mongoid/contextual/mongo.rb +2 -1
  32. data/lib/mongoid/criteria.rb +23 -4
  33. data/lib/mongoid/criteria/modifiable.rb +2 -1
  34. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  35. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -6
  36. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  37. data/lib/mongoid/criteria/queryable/mergeable.rb +75 -8
  38. data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
  39. data/lib/mongoid/criteria/queryable/selectable.rb +120 -13
  40. data/lib/mongoid/criteria/queryable/storable.rb +104 -99
  41. data/lib/mongoid/errors/eager_load.rb +2 -0
  42. data/lib/mongoid/errors/no_client_config.rb +2 -2
  43. data/lib/mongoid/errors/no_default_client.rb +1 -1
  44. data/lib/mongoid/extensions/hash.rb +4 -2
  45. data/lib/mongoid/extensions/regexp.rb +1 -1
  46. data/lib/mongoid/fields.rb +2 -1
  47. data/lib/mongoid/fields/standard.rb +2 -1
  48. data/lib/mongoid/fields/validators/macro.rb +4 -1
  49. data/lib/mongoid/findable.rb +5 -4
  50. data/lib/mongoid/interceptable.rb +5 -1
  51. data/lib/mongoid/matchable/regexp.rb +2 -2
  52. data/lib/mongoid/persistable/pushable.rb +11 -2
  53. data/lib/mongoid/persistence_context.rb +6 -6
  54. data/lib/mongoid/query_cache.rb +61 -18
  55. data/lib/mongoid/railties/database.rake +7 -0
  56. data/lib/mongoid/serializable.rb +10 -2
  57. data/lib/mongoid/shardable.rb +56 -4
  58. data/lib/mongoid/tasks/database.rake +10 -5
  59. data/lib/mongoid/tasks/database.rb +83 -0
  60. data/lib/mongoid/timestamps/timeless.rb +3 -1
  61. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  62. data/lib/mongoid/version.rb +1 -1
  63. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
  64. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  65. data/spec/app/models/coding.rb +4 -0
  66. data/spec/app/models/coding/pull_request.rb +12 -0
  67. data/spec/app/models/delegating_patient.rb +16 -0
  68. data/spec/app/models/passport.rb +1 -0
  69. data/spec/app/models/phone.rb +1 -0
  70. data/spec/app/models/publication.rb +5 -0
  71. data/spec/app/models/publication/encyclopedia.rb +12 -0
  72. data/spec/app/models/publication/review.rb +14 -0
  73. data/spec/integration/app_spec.rb +254 -0
  74. data/spec/integration/associations/embedded_spec.rb +54 -0
  75. data/spec/integration/associations/has_many_spec.rb +34 -0
  76. data/spec/integration/associations/has_one_spec.rb +34 -0
  77. data/spec/integration/bson_regexp_raw_spec.rb +20 -0
  78. data/spec/integration/criteria/date_field_spec.rb +41 -0
  79. data/spec/integration/criteria/logical_spec.rb +13 -0
  80. data/spec/integration/document_spec.rb +22 -0
  81. data/spec/integration/shardable_spec.rb +149 -0
  82. data/spec/lite_spec_helper.rb +15 -4
  83. data/spec/mongoid/association/accessors_spec.rb +238 -63
  84. data/spec/mongoid/association/embedded/embeds_many_models.rb +19 -0
  85. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  86. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  87. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
  88. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  89. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +146 -68
  90. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
  91. data/spec/mongoid/attributes_spec.rb +19 -7
  92. data/spec/mongoid/changeable_spec.rb +23 -0
  93. data/spec/mongoid/clients/factory_spec.rb +8 -8
  94. data/spec/mongoid/clients/options_spec.rb +11 -11
  95. data/spec/mongoid/clients/sessions_spec.rb +8 -4
  96. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  97. data/spec/mongoid/clients_spec.rb +2 -2
  98. data/spec/mongoid/contextual/atomic_spec.rb +22 -11
  99. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  100. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  101. data/spec/mongoid/contextual/mongo_spec.rb +76 -53
  102. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +1 -1
  103. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  104. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  105. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  106. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  107. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +45 -12
  108. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1051 -392
  109. data/spec/mongoid/criteria/queryable/selectable_spec.rb +52 -0
  110. data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
  111. data/spec/mongoid/criteria_spec.rb +36 -2
  112. data/spec/mongoid/document_fields_spec.rb +29 -0
  113. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  114. data/spec/mongoid/errors/no_client_config_spec.rb +2 -2
  115. data/spec/mongoid/errors/no_client_database_spec.rb +3 -3
  116. data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -3
  117. data/spec/mongoid/fields_spec.rb +24 -1
  118. data/spec/mongoid/indexable_spec.rb +6 -4
  119. data/spec/mongoid/interceptable_spec.rb +62 -0
  120. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  121. data/spec/mongoid/matchable/default_spec.rb +1 -1
  122. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  123. data/spec/mongoid/matchable_spec.rb +2 -2
  124. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  125. data/spec/mongoid/query_cache_spec.rb +77 -9
  126. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  127. data/spec/mongoid/scopable_spec.rb +2 -1
  128. data/spec/mongoid/serializable_spec.rb +129 -18
  129. data/spec/mongoid/shardable_models.rb +61 -0
  130. data/spec/mongoid/shardable_spec.rb +69 -16
  131. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  132. data/spec/mongoid/tasks/database_spec.rb +1 -1
  133. data/spec/spec_helper.rb +2 -31
  134. data/spec/support/child_process_helper.rb +76 -0
  135. data/spec/support/cluster_config.rb +3 -3
  136. data/spec/support/constraints.rb +26 -10
  137. data/spec/support/expectations.rb +3 -1
  138. data/spec/support/helpers.rb +11 -0
  139. data/spec/support/lite_constraints.rb +22 -0
  140. data/spec/support/session_registry.rb +50 -0
  141. data/spec/support/spec_config.rb +12 -4
  142. metadata +518 -480
  143. metadata.gz.sig +0 -0
@@ -2450,6 +2450,58 @@ describe Mongoid::Criteria::Queryable::Selectable do
2450
2450
  end
2451
2451
  end
2452
2452
  end
2453
+
2454
+ context 'when using an MQL logical operator manually' do
2455
+ let(:base_query) do
2456
+ query.where(test: 1)
2457
+ end
2458
+
2459
+ let(:selection) do
2460
+ base_query.where(mql_operator => ['hello' => 'world'])
2461
+ end
2462
+
2463
+ shared_examples_for 'adds conditions to existing query' do
2464
+ it 'adds conditions to existing query' do
2465
+ selection.selector.should == {
2466
+ 'test' => 1,
2467
+ mql_operator => ['hello' => 'world'],
2468
+ }
2469
+ end
2470
+ end
2471
+
2472
+ shared_examples_for 'adds conditions to existing query with an extra $and' do
2473
+ it 'adds conditions to existing query' do
2474
+ selection.selector.should == {
2475
+ 'test' => 1,
2476
+ mql_operator => ['hello' => 'world'],
2477
+ }
2478
+ end
2479
+ end
2480
+
2481
+ context '$or' do
2482
+ let(:mql_operator) { '$or' }
2483
+
2484
+ it_behaves_like 'adds conditions to existing query with an extra $and'
2485
+ end
2486
+
2487
+ context '$nor' do
2488
+ let(:mql_operator) { '$nor' }
2489
+
2490
+ it_behaves_like 'adds conditions to existing query with an extra $and'
2491
+ end
2492
+
2493
+ context '$not' do
2494
+ let(:mql_operator) { '$not' }
2495
+
2496
+ it_behaves_like 'adds conditions to existing query'
2497
+ end
2498
+
2499
+ context '$and' do
2500
+ let(:mql_operator) { '$and' }
2501
+
2502
+ it_behaves_like 'adds conditions to existing query'
2503
+ end
2504
+ end
2453
2505
  end
2454
2506
 
2455
2507
  describe Symbol do
@@ -52,6 +52,22 @@ describe Mongoid::Criteria::Queryable::Storable do
52
52
  end
53
53
  end
54
54
 
55
+ context '$and to query with $and which already has the given key' do
56
+ let(:query) do
57
+ Mongoid::Query.new.where('$and' => [{foo: 'zoom'}])
58
+ end
59
+
60
+ let(:modified) do
61
+ query.send(query_method, '$and', [{'foo' => 'bar'}])
62
+ end
63
+
64
+ it 'adds to existing $and' do
65
+ modified.selector.should == {
66
+ '$and' => [{'foo' => 'zoom'}, {'foo' => 'bar'}],
67
+ }
68
+ end
69
+ end
70
+
55
71
  end
56
72
 
57
73
  context '$or operator' do
@@ -74,9 +90,11 @@ describe Mongoid::Criteria::Queryable::Storable do
74
90
  query.send(query_method, '$or', [{'foo' => 'bar'}])
75
91
  end
76
92
 
77
- it 'replaces top level' do
93
+ it 'adds the new conditions' do
78
94
  modified.selector.should == {
79
- '$or' => [{'zoom' => 'zoom'}, {'foo' => 'bar'}]}
95
+ 'zoom' => 'zoom',
96
+ '$or' => ['foo' => 'bar'],
97
+ }
80
98
  end
81
99
  end
82
100
 
@@ -98,6 +116,66 @@ describe Mongoid::Criteria::Queryable::Storable do
98
116
  end
99
117
  end
100
118
 
119
+ describe '#add_field_expression' do
120
+ context 'simple field and value write' do
121
+ let(:modified) do
122
+ query.add_field_expression('foo', 'bar')
123
+ end
124
+
125
+ it 'adds the condition' do
126
+ modified.selector.should == {
127
+ 'foo' => 'bar'
128
+ }
129
+ end
130
+ end
131
+
132
+ context 'an operator write' do
133
+ let(:modified) do
134
+ query.add_field_expression('$eq', {'foo' => 'bar'})
135
+ end
136
+
137
+ it 'is not allowed' do
138
+ lambda do
139
+ modified
140
+ end.should raise_error(ArgumentError, /Field cannot be an operator/)
141
+ end
142
+ end
143
+
144
+ context 'when another field exists in destination' do
145
+ let(:base) do
146
+ query.add_field_expression('foo', 'bar')
147
+ end
148
+
149
+ let(:modified) do
150
+ base.add_field_expression('zoom', 'zoom')
151
+ end
152
+
153
+ it 'adds the condition' do
154
+ modified.selector.should == {
155
+ 'foo' => 'bar',
156
+ 'zoom' => 'zoom',
157
+ }
158
+ end
159
+ end
160
+
161
+ context 'when field being added already exists in destination' do
162
+ let(:base) do
163
+ query.add_field_expression('foo', 'bar')
164
+ end
165
+
166
+ let(:modified) do
167
+ base.add_field_expression('foo', 'zoom')
168
+ end
169
+
170
+ it 'adds the new condition using $and' do
171
+ modified.selector.should == {
172
+ 'foo' => 'bar',
173
+ '$and' => ['foo' => 'zoom'],
174
+ }
175
+ end
176
+ end
177
+ end
178
+
101
179
  describe '#add_operator_expression' do
102
180
  let(:query_method) { :add_operator_expression }
103
181
 
@@ -2337,7 +2337,7 @@ describe Mongoid::Criteria do
2337
2337
  end
2338
2338
 
2339
2339
  it "returns the map/reduce results" do
2340
- expect(map_reduce).to eq([
2340
+ expect(map_reduce.sort_by { |doc| doc['_id'] }).to eq([
2341
2341
  { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
2342
2342
  { "_id" => "Tool", "value" => { "likes" => 100 }}
2343
2343
  ])
@@ -3428,6 +3428,38 @@ describe Mongoid::Criteria do
3428
3428
  Band.create(name: "Tool")
3429
3429
  end
3430
3430
 
3431
+ context 'when provided no arguments' do
3432
+ context 'on a model class' do
3433
+ it 'returns an empty criteria' do
3434
+ Band.where.selector.should == {}
3435
+ end
3436
+ end
3437
+
3438
+ context 'on an association' do
3439
+ it 'returns an empty criteria' do
3440
+ match.records.where.selector.should == {}
3441
+ end
3442
+ end
3443
+ end
3444
+
3445
+ context 'when provided multiple arguments' do
3446
+ context 'on a model class' do
3447
+ it 'raises ArgumentError' do
3448
+ lambda do
3449
+ Band.where({foo: 1}, {bar: 2})
3450
+ end.should raise_error(ArgumentError, /where requires zero or one arguments/)
3451
+ end
3452
+ end
3453
+
3454
+ context 'on an association' do
3455
+ it 'raises ArgumentError' do
3456
+ lambda do
3457
+ match.records.where({foo: 1}, {bar: 2})
3458
+ end.should raise_error(ArgumentError, /where requires zero or one arguments/)
3459
+ end
3460
+ end
3461
+ end
3462
+
3431
3463
  context "when provided a string" do
3432
3464
 
3433
3465
  context "when the criteria is embedded" do
@@ -3502,7 +3534,8 @@ describe Mongoid::Criteria do
3502
3534
  end
3503
3535
  end
3504
3536
 
3505
- context "when querying on a BSON::Decimal128", if: decimal128_supported? do
3537
+ context "when querying on a BSON::Decimal128" do
3538
+ min_server_version '3.4'
3506
3539
 
3507
3540
  let(:decimal) do
3508
3541
  BSON::Decimal128.new("0.0005")
@@ -3590,6 +3623,7 @@ describe Mongoid::Criteria do
3590
3623
  end
3591
3624
 
3592
3625
  context "when the code has scope" do
3626
+ max_server_version '4.2'
3593
3627
 
3594
3628
  let(:criteria) do
3595
3629
  Band.for_js("this.name == param", param: "Depeche Mode")
@@ -56,4 +56,33 @@ describe Mongoid::Document do
56
56
  end
57
57
  end
58
58
  end
59
+
60
+ describe 'Hash field' do
61
+ context 'with symbol key and value' do
62
+ let(:church) do
63
+ Church.create!(location: {state: :ny})
64
+ end
65
+
66
+ let(:found_church) do
67
+ Church.find(church.id)
68
+ end
69
+
70
+ it 'round-trips the value' do
71
+ found_church.location[:state].should == :ny
72
+ end
73
+
74
+ it 'stringifies the key' do
75
+ found_church.location.keys.should == %w(state)
76
+ end
77
+
78
+ it 'retrieves value as symbol via driver' do
79
+ Church.delete_all
80
+
81
+ church
82
+
83
+ v = Church.collection.find.first
84
+ v['location'].should == {'state' => :ny}
85
+ end
86
+ end
87
+ end
59
88
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require "spec_helper"
5
+
6
+ describe Mongoid::Document do
7
+
8
+ let(:klass) do
9
+ Person
10
+ end
11
+
12
+ let(:person) do
13
+ Person.new
14
+ end
15
+
16
+ describe '.client_name' do
17
+ it 'returns client name' do
18
+ Person.client_name.should == :default
19
+ end
20
+ end
21
+
22
+ describe '.database_name' do
23
+ it 'returns database name' do
24
+ Person.database_name.should == 'mongoid_test'
25
+ end
26
+ end
27
+
28
+ describe '.collection_name' do
29
+ it 'returns collection name' do
30
+ Person.collection_name.should == :people
31
+ end
32
+ end
33
+ end
@@ -8,12 +8,12 @@ describe Mongoid::Errors::NoClientConfig do
8
8
  describe "#message" do
9
9
 
10
10
  let(:error) do
11
- described_class.new(:secondary)
11
+ described_class.new(:analytics)
12
12
  end
13
13
 
14
14
  it "contains the problem in the message" do
15
15
  expect(error.message).to include(
16
- "No configuration could be found for a client named 'secondary'."
16
+ "No configuration could be found for a client named 'analytics'."
17
17
  )
18
18
  end
19
19
 
@@ -8,12 +8,12 @@ describe Mongoid::Errors::NoClientDatabase do
8
8
  describe "#message" do
9
9
 
10
10
  let(:error) do
11
- described_class.new(:secondary, { hosts: [ "127.0.0.1:27017" ] })
11
+ described_class.new(:analytics, { hosts: [ "127.0.0.1:27017" ] })
12
12
  end
13
13
 
14
14
  it "contains the problem in the message" do
15
15
  expect(error.message).to include(
16
- "No database provided for client configuration: :secondary."
16
+ "No database provided for client configuration: :analytics."
17
17
  )
18
18
  end
19
19
 
@@ -25,7 +25,7 @@ describe Mongoid::Errors::NoClientDatabase do
25
25
 
26
26
  it "contains the resolution in the message" do
27
27
  expect(error.message).to include(
28
- "If configuring via a mongoid.yml, ensure that within your :secondary"
28
+ "If configuring via a mongoid.yml, ensure that within your :analytics"
29
29
  )
30
30
  end
31
31
  end
@@ -8,12 +8,12 @@ describe Mongoid::Errors::NoClientHosts do
8
8
  describe "#message" do
9
9
 
10
10
  let(:error) do
11
- described_class.new(:secondary, { database: "mongoid_test" })
11
+ described_class.new(:analytics, { database: "mongoid_test" })
12
12
  end
13
13
 
14
14
  it "contains the problem in the message" do
15
15
  expect(error.message).to include(
16
- "No hosts provided for client configuration: :secondary."
16
+ "No hosts provided for client configuration: :analytics."
17
17
  )
18
18
  end
19
19
 
@@ -25,7 +25,7 @@ describe Mongoid::Errors::NoClientHosts do
25
25
 
26
26
  it "contains the resolution in the message" do
27
27
  expect(error.message).to include(
28
- "If configuring via a mongoid.yml, ensure that within your :secondary"
28
+ "If configuring via a mongoid.yml, ensure that within your :analytics"
29
29
  )
30
30
  end
31
31
  end
@@ -431,7 +431,9 @@ describe Mongoid::Fields do
431
431
  context "when the Symbol type is used" do
432
432
 
433
433
  before do
434
- expect(Mongoid.logger).to receive(:warn)
434
+ Mongoid::Fields::Validators::Macro.class_eval do
435
+ @field_type_is_symbol_warned = false
436
+ end
435
437
  end
436
438
 
437
439
  after do
@@ -439,8 +441,29 @@ describe Mongoid::Fields do
439
441
  end
440
442
 
441
443
  it "warns that the BSON symbol type is deprecated" do
444
+ expect(Mongoid.logger).to receive(:warn)
445
+
446
+ Band.field :should_warn, type: Symbol
447
+ end
448
+
449
+ it "warns on first use of Symbol type only" do
450
+ expect(Mongoid.logger).to receive(:warn).once
451
+
442
452
  Band.field :should_warn, type: Symbol
443
453
  end
454
+
455
+ context 'when using Symbol field type in multiple classes' do
456
+ after do
457
+ Truck.fields.delete("should_warn")
458
+ end
459
+
460
+ it "warns on first use of Symbol type only" do
461
+ expect(Mongoid.logger).to receive(:warn).once
462
+
463
+ Band.field :should_warn, type: Symbol
464
+ Truck.field :should_warn, type: Symbol
465
+ end
466
+ end
444
467
  end
445
468
 
446
469
  context "when the options are not valid" do
@@ -48,7 +48,7 @@ describe Mongoid::Indexable do
48
48
  end
49
49
  end
50
50
 
51
- context "when database specific options exist", if: non_legacy_server? do
51
+ context "when database specific options exist" do
52
52
 
53
53
  let(:klass) do
54
54
  Class.new do
@@ -98,7 +98,7 @@ describe Mongoid::Indexable do
98
98
  end
99
99
  end
100
100
 
101
- context "when database options are specified", if: non_legacy_server? do
101
+ context "when database options are specified" do
102
102
 
103
103
  let(:klass) do
104
104
  Class.new do
@@ -136,7 +136,8 @@ describe Mongoid::Indexable do
136
136
  end
137
137
  end
138
138
 
139
- context "when a collation option is specified", if: collation_supported? do
139
+ context "when a collation option is specified" do
140
+ min_server_version '3.4'
140
141
 
141
142
  let(:klass) do
142
143
  Class.new do
@@ -311,7 +312,8 @@ describe Mongoid::Indexable do
311
312
  end
312
313
  end
313
314
 
314
- context "when providing a collation option", if: collation_supported? do
315
+ context "when providing a collation option" do
316
+ min_server_version '3.4'
315
317
 
316
318
  before do
317
319
  klass.index({ name: 1 }, collation: { locale: 'en_US', strength: 2 })
@@ -2,6 +2,7 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  require "spec_helper"
5
+ require_relative './interceptable_spec_models'
5
6
 
6
7
  describe Mongoid::Interceptable do
7
8
 
@@ -1722,4 +1723,65 @@ describe Mongoid::Interceptable do
1722
1723
  end
1723
1724
  end
1724
1725
  end
1726
+
1727
+ context 'when creating a parent and embedded child' do
1728
+ let(:registry) { InterceptableSpec::CallbackRegistry.new }
1729
+ let(:parent) do
1730
+ InterceptableSpec::CbParent.new(registry).tap do |parent|
1731
+ parent.cb_children << InterceptableSpec::CbChild.new(registry, cb_parent: parent)
1732
+ end
1733
+ end
1734
+
1735
+ let(:expected) do
1736
+ [
1737
+ [InterceptableSpec::CbParent, :before_validation],
1738
+ [InterceptableSpec::CbChild, :before_validation],
1739
+ [InterceptableSpec::CbChild, :after_validation],
1740
+ [InterceptableSpec::CbParent, :after_validation],
1741
+ [InterceptableSpec::CbParent, :before_save],
1742
+ [InterceptableSpec::CbParent, :before_create],
1743
+ [InterceptableSpec::CbParent, :after_create],
1744
+ [InterceptableSpec::CbParent, :after_save],
1745
+ ]
1746
+ end
1747
+
1748
+ it 'calls callbacks in the right order' do
1749
+ parent.save!
1750
+ expect(registry.calls).to eq expected
1751
+ end
1752
+ end
1753
+
1754
+ context 'when creating a parent and embedded child with cascading callbacks' do
1755
+ let(:registry) { InterceptableSpec::CallbackRegistry.new }
1756
+ let(:parent) do
1757
+ InterceptableSpec::CbParent.new(registry).tap do |parent|
1758
+ parent.cb_cascaded_children <<
1759
+ InterceptableSpec::CbCascadedChild.new(registry, cb_parent: parent)
1760
+ end
1761
+ end
1762
+
1763
+ let(:expected) do
1764
+ [
1765
+ [InterceptableSpec::CbParent, :before_validation],
1766
+ [InterceptableSpec::CbCascadedChild, :before_validation],
1767
+ [InterceptableSpec::CbCascadedChild, :after_validation],
1768
+ [InterceptableSpec::CbParent, :after_validation],
1769
+ [InterceptableSpec::CbParent, :before_save],
1770
+ [InterceptableSpec::CbCascadedChild, :before_save],
1771
+ [InterceptableSpec::CbParent, :before_create],
1772
+ [InterceptableSpec::CbCascadedChild, :before_create],
1773
+ [InterceptableSpec::CbParent, :after_create],
1774
+ [InterceptableSpec::CbCascadedChild, :after_create],
1775
+ [InterceptableSpec::CbParent, :after_save],
1776
+ [InterceptableSpec::CbCascadedChild, :after_save],
1777
+ ]
1778
+ end
1779
+
1780
+ it 'calls callbacks in the right order' do
1781
+ pending 'MONGOID-3795'
1782
+
1783
+ parent.save!
1784
+ expect(registry.calls).to eq expected
1785
+ end
1786
+ end
1725
1787
  end