mongoid 8.0.3 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +3 -3
  4. data/README.md +3 -3
  5. data/lib/config/locales/en.yml +46 -14
  6. data/lib/mongoid/association/accessors.rb +2 -2
  7. data/lib/mongoid/association/builders.rb +1 -1
  8. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  9. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  10. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  11. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  12. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +23 -21
  13. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  14. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  15. data/lib/mongoid/association/nested/one.rb +40 -2
  16. data/lib/mongoid/association/proxy.rb +1 -1
  17. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +5 -1
  19. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_many/proxy.rb +7 -3
  21. data/lib/mongoid/association/reflections.rb +2 -2
  22. data/lib/mongoid/attributes/dynamic.rb +1 -1
  23. data/lib/mongoid/attributes/nested.rb +2 -2
  24. data/lib/mongoid/attributes/projector.rb +1 -1
  25. data/lib/mongoid/attributes/readonly.rb +1 -1
  26. data/lib/mongoid/attributes.rb +8 -2
  27. data/lib/mongoid/changeable.rb +104 -4
  28. data/lib/mongoid/clients/storage_options.rb +2 -5
  29. data/lib/mongoid/clients/validators/storage.rb +1 -13
  30. data/lib/mongoid/collection_configurable.rb +58 -0
  31. data/lib/mongoid/composable.rb +2 -0
  32. data/lib/mongoid/config/defaults.rb +60 -0
  33. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  34. data/lib/mongoid/config/validators.rb +1 -0
  35. data/lib/mongoid/config.rb +101 -0
  36. data/lib/mongoid/contextual/atomic.rb +1 -1
  37. data/lib/mongoid/contextual/memory.rb +233 -33
  38. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  39. data/lib/mongoid/contextual/mongo.rb +373 -113
  40. data/lib/mongoid/contextual/none.rb +162 -7
  41. data/lib/mongoid/contextual.rb +12 -0
  42. data/lib/mongoid/criteria/findable.rb +2 -2
  43. data/lib/mongoid/criteria/includable.rb +4 -3
  44. data/lib/mongoid/criteria/queryable/extensions/array.rb +1 -1
  45. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -1
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +0 -8
  47. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -11
  48. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +0 -10
  49. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  50. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  51. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  52. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  53. data/lib/mongoid/criteria/translator.rb +45 -0
  54. data/lib/mongoid/criteria.rb +7 -5
  55. data/lib/mongoid/deprecable.rb +1 -1
  56. data/lib/mongoid/document.rb +50 -13
  57. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  58. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  59. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  60. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  61. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  62. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  63. data/lib/mongoid/errors.rb +4 -1
  64. data/lib/mongoid/extensions/object.rb +2 -2
  65. data/lib/mongoid/extensions/time.rb +2 -0
  66. data/lib/mongoid/factory.rb +21 -8
  67. data/lib/mongoid/fields/localized.rb +10 -0
  68. data/lib/mongoid/fields/standard.rb +10 -0
  69. data/lib/mongoid/fields.rb +69 -13
  70. data/lib/mongoid/findable.rb +27 -3
  71. data/lib/mongoid/interceptable.rb +7 -6
  72. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  73. data/lib/mongoid/matcher/type.rb +1 -1
  74. data/lib/mongoid/matcher.rb +21 -6
  75. data/lib/mongoid/persistable/creatable.rb +1 -0
  76. data/lib/mongoid/persistable/deletable.rb +1 -1
  77. data/lib/mongoid/persistable/savable.rb +13 -1
  78. data/lib/mongoid/persistable/unsettable.rb +2 -2
  79. data/lib/mongoid/persistable/updatable.rb +51 -1
  80. data/lib/mongoid/persistable/upsertable.rb +20 -1
  81. data/lib/mongoid/persistable.rb +3 -0
  82. data/lib/mongoid/query_cache.rb +5 -1
  83. data/lib/mongoid/railties/database.rake +7 -2
  84. data/lib/mongoid/shardable.rb +35 -11
  85. data/lib/mongoid/stateful.rb +22 -1
  86. data/lib/mongoid/tasks/database.rake +12 -0
  87. data/lib/mongoid/tasks/database.rb +20 -0
  88. data/lib/mongoid/threaded.rb +30 -0
  89. data/lib/mongoid/traversable.rb +1 -1
  90. data/lib/mongoid/utils.rb +22 -0
  91. data/lib/mongoid/validatable/macros.rb +5 -5
  92. data/lib/mongoid/validatable.rb +4 -1
  93. data/lib/mongoid/version.rb +1 -1
  94. data/lib/mongoid/warnings.rb +17 -1
  95. data/lib/mongoid.rb +16 -3
  96. data/spec/integration/app_spec.rb +2 -2
  97. data/spec/integration/callbacks_models.rb +37 -0
  98. data/spec/integration/callbacks_spec.rb +134 -0
  99. data/spec/integration/discriminator_key_spec.rb +4 -5
  100. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  101. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  102. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +57 -57
  103. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  104. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  105. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  106. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +148 -224
  107. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +111 -164
  108. data/spec/mongoid/association/syncable_spec.rb +1 -1
  109. data/spec/mongoid/attributes_spec.rb +5 -8
  110. data/spec/mongoid/changeable_spec.rb +299 -24
  111. data/spec/mongoid/clients_spec.rb +122 -13
  112. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  113. data/spec/mongoid/config/defaults_spec.rb +160 -0
  114. data/spec/mongoid/config_spec.rb +154 -18
  115. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  116. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  117. data/spec/mongoid/contextual/mongo_spec.rb +995 -36
  118. data/spec/mongoid/contextual/none_spec.rb +49 -2
  119. data/spec/mongoid/copyable_spec.rb +3 -11
  120. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  121. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  122. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -0
  123. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  124. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  125. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  126. data/spec/mongoid/criteria/queryable/selector_spec.rb +1 -1
  127. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  128. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  129. data/spec/mongoid/criteria_spec.rb +5 -9
  130. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  131. data/spec/mongoid/extensions/time_spec.rb +8 -43
  132. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  133. data/spec/mongoid/fields/localized_spec.rb +46 -28
  134. data/spec/mongoid/fields_spec.rb +136 -34
  135. data/spec/mongoid/findable_spec.rb +391 -34
  136. data/spec/mongoid/indexable_spec.rb +16 -10
  137. data/spec/mongoid/interceptable_spec.rb +15 -3
  138. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  139. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  140. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  141. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  142. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  143. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  144. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  145. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  146. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  147. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  148. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  149. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  150. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  151. data/spec/mongoid/persistence_context_spec.rb +7 -57
  152. data/spec/mongoid/query_cache_spec.rb +56 -61
  153. data/spec/mongoid/reloadable_spec.rb +24 -4
  154. data/spec/mongoid/scopable_spec.rb +70 -0
  155. data/spec/mongoid/serializable_spec.rb +9 -30
  156. data/spec/mongoid/shardable_models.rb +14 -0
  157. data/spec/mongoid/shardable_spec.rb +153 -61
  158. data/spec/mongoid/stateful_spec.rb +122 -8
  159. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  160. data/spec/mongoid/tasks/database_spec.rb +127 -0
  161. data/spec/mongoid/timestamps_spec.rb +9 -11
  162. data/spec/mongoid/touchable_spec.rb +277 -5
  163. data/spec/mongoid/touchable_spec_models.rb +3 -1
  164. data/spec/mongoid/traversable_spec.rb +9 -24
  165. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  166. data/spec/mongoid_spec.rb +35 -9
  167. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  168. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  169. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  170. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  171. data/spec/shared/lib/mrss/utils.rb +28 -6
  172. data/spec/shared/share/Dockerfile.erb +36 -40
  173. data/spec/shared/shlib/server.sh +32 -8
  174. data/spec/shared/shlib/set_env.sh +4 -4
  175. data/spec/spec_helper.rb +5 -0
  176. data/spec/support/immutable_ids.rb +118 -0
  177. data/spec/support/macros.rb +47 -15
  178. data/spec/support/models/artist.rb +0 -1
  179. data/spec/support/models/band.rb +1 -0
  180. data/spec/support/models/book.rb +1 -0
  181. data/spec/support/models/building.rb +2 -0
  182. data/spec/support/models/cover.rb +10 -0
  183. data/spec/support/models/product.rb +1 -0
  184. data.tar.gz.sig +0 -0
  185. metadata +700 -656
  186. metadata.gz.sig +0 -0
  187. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
@@ -27,11 +27,11 @@ describe Mongoid::Shardable do
27
27
  context 'when full syntax is used' do
28
28
  context 'with symbol value' do
29
29
  it 'sets shard key fields to symbol value' do
30
- SmProducer.shard_key_fields.should == %i(age gender)
30
+ expect(SmProducer.shard_key_fields).to be == %i(age gender)
31
31
  end
32
32
 
33
33
  it 'sets shard config' do
34
- SmProducer.shard_config.should == {
34
+ expect(SmProducer.shard_config).to be == {
35
35
  key: {age: 1, gender: 'hashed'},
36
36
  options: {
37
37
  unique: true,
@@ -41,37 +41,37 @@ describe Mongoid::Shardable do
41
41
  end
42
42
 
43
43
  it 'keeps hashed as string' do
44
- SmProducer.shard_config[:key][:gender].should == 'hashed'
44
+ expect(SmProducer.shard_config[:key][:gender]).to be == 'hashed'
45
45
  end
46
46
  end
47
47
 
48
48
  context 'with string value' do
49
49
  it 'sets shard key fields to symbol value' do
50
- SmActor.shard_key_fields.should == %i(age gender hello)
50
+ expect(SmActor.shard_key_fields).to be == %i(age gender hello)
51
51
  end
52
52
 
53
53
  it 'sets shard config' do
54
- SmActor.shard_config.should == {
54
+ expect(SmActor.shard_config).to be == {
55
55
  key: {age: 1, gender: 'hashed', hello: 'hashed'},
56
56
  options: {},
57
57
  }
58
58
  end
59
59
 
60
60
  it 'sets hashed to string' do
61
- SmActor.shard_config[:key][:gender].should == 'hashed'
61
+ expect(SmActor.shard_config[:key][:gender]).to be == 'hashed'
62
62
  end
63
63
  end
64
64
 
65
65
  context 'when passed association name' do
66
66
  it 'uses foreign key as shard key in shard config' do
67
- SmDriver.shard_config.should == {
67
+ expect(SmDriver.shard_config).to be == {
68
68
  key: {age: 1, agency_id: 'hashed'},
69
69
  options: {},
70
70
  }
71
71
  end
72
72
 
73
73
  it 'uses foreign key as shard key in shard key fields' do
74
- SmDriver.shard_key_fields.should == %i(age agency_id)
74
+ expect(SmDriver.shard_key_fields).to be == %i(age agency_id)
75
75
  end
76
76
  end
77
77
  end
@@ -79,26 +79,26 @@ describe Mongoid::Shardable do
79
79
  context 'when shorthand syntax is used' do
80
80
  context 'with symbol value' do
81
81
  it 'sets shard key fields to symbol value' do
82
- SmMovie.shard_key_fields.should == %i(year)
82
+ expect(SmMovie.shard_key_fields).to be == %i(year)
83
83
  end
84
84
  end
85
85
 
86
86
  context 'with string value' do
87
87
  it 'sets shard key fields to symbol value' do
88
- SmTrailer.shard_key_fields.should == %i(year)
88
+ expect(SmTrailer.shard_key_fields).to be == %i(year)
89
89
  end
90
90
  end
91
91
 
92
92
  context 'when passed association name' do
93
93
  it 'uses foreign key as shard key in shard config' do
94
- SmDirector.shard_config.should == {
94
+ expect(SmDirector.shard_config).to be == {
95
95
  key: {agency_id: 1},
96
96
  options: {},
97
97
  }
98
98
  end
99
99
 
100
100
  it 'uses foreign key as shard key in shard key fields' do
101
- SmDirector.shard_key_fields.should == %i(agency_id)
101
+ expect(SmDirector.shard_key_fields).to be == %i(agency_id)
102
102
  end
103
103
  end
104
104
  end
@@ -106,41 +106,80 @@ describe Mongoid::Shardable do
106
106
 
107
107
  describe '#shard_key_selector' do
108
108
  subject { instance.shard_key_selector }
109
- let(:klass) { Band }
110
- let(:value) { 'a-brand-name' }
109
+
110
+ context 'when key is an immediate attribute' do
111
+ let(:klass) { Band }
112
+ let(:value) { 'a-brand-name' }
111
113
 
112
- before { klass.shard_key(:name) }
114
+ before { klass.shard_key(:name) }
113
115
 
114
- context 'when record is new' do
115
- let(:instance) { klass.new(name: value) }
116
+ context 'when record is new' do
117
+ let(:instance) { klass.new(name: value) }
116
118
 
117
- it { is_expected.to eq({ 'name' => value }) }
119
+ it { is_expected.to eq({ 'name' => value }) }
118
120
 
119
- context 'changing shard key value' do
120
- let(:new_value) { 'a-new-value' }
121
+ context 'changing shard key value' do
122
+ let(:new_value) { 'a-new-value' }
121
123
 
122
- before do
123
- instance.name = new_value
124
+ before do
125
+ instance.name = new_value
126
+ end
127
+
128
+ it { is_expected.to eq({ 'name' => new_value }) }
124
129
  end
130
+ end
131
+
132
+ context 'when record is persisted' do
133
+ let(:instance) { klass.create!(name: value) }
125
134
 
126
- it { is_expected.to eq({ 'name' => new_value }) }
135
+ it { is_expected.to eq({ 'name' => value }) }
136
+
137
+ context 'changing shard key value' do
138
+ let(:new_value) { 'a-new-value' }
139
+
140
+ before do
141
+ instance.name = new_value
142
+ end
143
+
144
+ it { is_expected.to eq({ 'name' => new_value }) }
145
+ end
127
146
  end
128
147
  end
129
148
 
130
- context 'when record is persisted' do
131
- let(:instance) { klass.create!(name: value) }
149
+ context 'when key is an embedded attribute' do
150
+ let(:klass) { SmReview }
151
+ let(:value) { 'Arthur Conan Doyle' }
152
+ let(:key) { 'author.name' }
132
153
 
133
- it { is_expected.to eq({ 'name' => value }) }
154
+ context 'when record is new' do
155
+ let(:instance) { klass.new(author: { name: value }) }
134
156
 
135
- context 'changing shard key value' do
136
- let(:new_value) { 'a-new-value' }
157
+ it { is_expected.to eq({ key => value }) }
137
158
 
138
- before do
139
- instance.name = new_value
159
+ context 'changing shard key value' do
160
+ let(:new_value) { 'Jules Verne' }
161
+
162
+ before do
163
+ instance.author.name = new_value
164
+ end
165
+
166
+ it { is_expected.to eq({ key => new_value }) }
140
167
  end
168
+ end
169
+
170
+ context 'when record is persisted' do
171
+ let(:instance) { klass.create!(author: { name: value }) }
172
+
173
+ it { is_expected.to eq({ key => value }) }
174
+
175
+ context 'changing shard key value' do
176
+ let(:new_value) { 'Jules Verne' }
141
177
 
142
- it 'uses the newly set shard key value' do
143
- subject.should == { 'name' => new_value }
178
+ before do
179
+ instance.author.name = new_value
180
+ end
181
+
182
+ it { is_expected.to eq({ 'author.name' => new_value }) }
144
183
  end
145
184
  end
146
185
  end
@@ -148,56 +187,109 @@ describe Mongoid::Shardable do
148
187
 
149
188
  describe '#shard_key_selector_in_db' do
150
189
  subject { instance.shard_key_selector_in_db }
151
- let(:klass) { Band }
152
- let(:value) { 'a-brand-name' }
153
190
 
154
- before { klass.shard_key(:name) }
191
+ context 'when key is an immediate attribute' do
192
+ let(:klass) { Band }
193
+ let(:value) { 'a-brand-name' }
155
194
 
156
- context 'when record is new' do
157
- let(:instance) { klass.new(name: value) }
195
+ before { klass.shard_key(:name) }
158
196
 
159
- it { is_expected.to eq({ 'name' => value }) }
197
+ context 'when record is new' do
198
+ let(:instance) { klass.new(name: value) }
160
199
 
161
- context 'changing shard key value' do
162
- let(:new_value) { 'a-new-value' }
200
+ it { is_expected.to eq({ 'name' => value }) }
163
201
 
164
- before do
165
- instance.name = new_value
166
- end
202
+ context 'changing shard key value' do
203
+ let(:new_value) { 'a-new-value' }
204
+
205
+ before do
206
+ instance.name = new_value
207
+ end
167
208
 
168
- it 'uses the existing shard key value' do
169
- subject.should == { 'name' => new_value }
209
+ it { is_expected.to eq({ 'name' => new_value }) }
170
210
  end
171
211
  end
172
- end
173
212
 
174
- context 'when record is persisted' do
175
- let(:instance) { klass.create!(name: value) }
213
+ context 'when record is persisted' do
214
+ let(:instance) { klass.create!(name: value) }
215
+
216
+ it { is_expected.to eq({ 'name' => value }) }
217
+
218
+ context 'changing shard key value' do
219
+ let(:new_value) { 'a-new-value' }
176
220
 
177
- it { is_expected.to eq({ 'name' => value }) }
221
+ before do
222
+ instance.name = new_value
223
+ end
178
224
 
179
- context 'changing shard key value' do
180
- let(:new_value) { 'a-new-value' }
225
+ it { is_expected.to eq({ 'name' => value }) }
226
+ end
227
+ end
228
+
229
+ context "when record is not found" do
230
+ let!(:instance) { klass.create!(name: value) }
181
231
 
182
232
  before do
183
- instance.name = new_value
233
+ instance.destroy
184
234
  end
185
235
 
186
- it { is_expected.to eq({ 'name' => value }) }
236
+ it "raises a DocumentNotFound error with the shard key in the description on reload" do
237
+ expect do
238
+ instance.reload
239
+ end.to raise_error(Mongoid::Errors::DocumentNotFound, /Document not found for class Band with id #{instance.id.to_s} and shard key name: a-brand-name./)
240
+ end
187
241
  end
188
242
  end
189
243
 
190
- context "when record is not found" do
191
- let!(:instance) { klass.create!(name: value) }
244
+ context 'when key is an embedded attribute' do
245
+ let(:klass) { SmReview }
246
+ let(:value) { 'Arthur Conan Doyle' }
247
+ let(:key) { 'author.name' }
248
+
249
+ context 'when record is new' do
250
+ let(:instance) { klass.new(author: { name: value }) }
251
+
252
+ it { is_expected.to eq({ key => value }) }
192
253
 
193
- before do
194
- instance.destroy
254
+ context 'changing shard key value' do
255
+ let(:new_value) { 'Jules Verne' }
256
+
257
+ before do
258
+ instance.author.name = new_value
259
+ end
260
+
261
+ it { is_expected.to eq({ key => new_value }) }
262
+ end
195
263
  end
196
264
 
197
- it "raises a DocumentNotFound error with the shard key in the description on reload" do
198
- expect do
199
- instance.reload
200
- end.to raise_error(Mongoid::Errors::DocumentNotFound, /Document not found for class Band with id #{instance.id.to_s} and shard key name: a-brand-name./)
265
+ context 'when record is persisted' do
266
+ let(:instance) { klass.create!(author: { name: value }) }
267
+
268
+ it { is_expected.to eq({ key => value }) }
269
+
270
+ context 'changing shard key value' do
271
+ let(:new_value) { 'Jules Verne' }
272
+
273
+ before do
274
+ instance.author.name = new_value
275
+ end
276
+
277
+ it { is_expected.to eq({ key => value }) }
278
+ end
279
+
280
+ context "when record is not found" do
281
+ let!(:instance) { klass.create!(author: { name: value }) }
282
+
283
+ before do
284
+ instance.destroy
285
+ end
286
+
287
+ it "raises a DocumentNotFound error with the shard key in the description on reload" do
288
+ expect do
289
+ instance.reload
290
+ end.to raise_error(Mongoid::Errors::DocumentNotFound, /Document not found for class SmReview with id #{instance.id.to_s} and shard key author.name: Arthur Conan Doyle./)
291
+ end
292
+ end
201
293
  end
202
294
  end
203
295
  end
@@ -136,21 +136,135 @@ describe Mongoid::Stateful do
136
136
  Band.new
137
137
  end
138
138
 
139
- context "when the document is readonly" do
139
+ context "when legacy_readonly is true" do
140
+ config_override :legacy_readonly, true
140
141
 
141
- before do
142
- document.__selected_fields = { test: 1 }
142
+ context "when the selected fields are set" do
143
+
144
+ before do
145
+ document.__selected_fields = { test: 1 }
146
+ end
147
+
148
+ it "returns true" do
149
+ expect(document).to be_readonly
150
+ end
143
151
  end
144
152
 
145
- it "returns true" do
146
- expect(document).to be_readonly
153
+ context "when no readonly has been set" do
154
+
155
+ it "returns false" do
156
+ expect(document).to_not be_readonly
157
+ end
158
+ end
159
+
160
+ context "when the readonly! method is called" do
161
+
162
+ let(:op) do
163
+ document.readonly!
164
+ end
165
+
166
+ it "returns false" do
167
+ op
168
+ expect(document).to_not be_readonly
169
+ end
170
+
171
+ it "warns" do
172
+ expect(Mongoid::Warnings).to receive(:warn_legacy_readonly)
173
+ op
174
+ end
175
+ end
176
+
177
+ context "when overriding readonly?" do
178
+
179
+ let(:doc) { ReadonlyModel.create! }
180
+
181
+ before do
182
+ class ReadonlyModel
183
+ include Mongoid::Document
184
+
185
+ attr_accessor :locked
186
+
187
+ def readonly?
188
+ !!locked
189
+ end
190
+ end
191
+ end
192
+
193
+ after do
194
+ Object.send(:remove_const, :ReadonlyModel)
195
+ end
196
+
197
+ it "raises when readonly? is true" do
198
+ expect(doc.readonly?).to be false
199
+ doc.locked = true
200
+ expect(doc.readonly?).to be true
201
+ expect do
202
+ doc.destroy
203
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
204
+ end
147
205
  end
148
206
  end
149
207
 
150
- context "when no readonly has been set" do
208
+ context "when legacy_readonly is false" do
209
+ config_override :legacy_readonly, false
151
210
 
152
- it "returns false" do
153
- expect(document).to_not be_readonly
211
+ context "when the selected fields are set" do
212
+
213
+ before do
214
+ document.__selected_fields = { test: 1 }
215
+ end
216
+
217
+ it "returns false" do
218
+ expect(document).to_not be_readonly
219
+ end
220
+ end
221
+
222
+ context "when the readonly! method is called" do
223
+
224
+ before do
225
+ document.readonly!
226
+ end
227
+
228
+ it "returns true" do
229
+ expect(document).to be_readonly
230
+ end
231
+ end
232
+
233
+ context "when no readonly has been set" do
234
+
235
+ it "returns false" do
236
+ expect(document).to_not be_readonly
237
+ end
238
+ end
239
+
240
+ context "when overriding readonly?" do
241
+
242
+ let(:doc) { ReadonlyModel.new }
243
+
244
+ before do
245
+ class ReadonlyModel
246
+ include Mongoid::Document
247
+
248
+ attr_accessor :locked
249
+
250
+ def readonly?
251
+ !!locked
252
+ end
253
+ end
254
+ end
255
+
256
+ after do
257
+ Object.send(:remove_const, :ReadonlyModel)
258
+ end
259
+
260
+ it "raises when readonly? is true" do
261
+ expect(doc.readonly?).to be false
262
+ doc.locked = true
263
+ expect(doc.readonly?).to be true
264
+ expect do
265
+ doc.save!
266
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
267
+ end
154
268
  end
155
269
  end
156
270
  end
@@ -35,6 +35,22 @@ shared_context "rake task" do
35
35
  task.invoke
36
36
  end
37
37
  end
38
+
39
+ shared_examples_for "create_collections" do
40
+
41
+ it "receives create_collections" do
42
+ expect(Mongoid::Tasks::Database).to receive(:create_collections)
43
+ task.invoke
44
+ end
45
+ end
46
+
47
+ shared_examples_for "force create_collections" do
48
+
49
+ it "receives create_collections" do
50
+ expect(Mongoid::Tasks::Database).to receive(:create_collections).with(force: true)
51
+ task.invoke
52
+ end
53
+ end
38
54
  end
39
55
 
40
56
  shared_context "rails rake task" do
@@ -99,6 +115,10 @@ describe "db:setup" do
99
115
  expect(task.prerequisites).to include("mongoid:create_indexes")
100
116
  end
101
117
 
118
+ it "calls db:mongoid:create_collections" do
119
+ expect(task.prerequisites).to include("mongoid:create_collections")
120
+ end
121
+
102
122
  it "calls db:seed" do
103
123
  expect(task.prerequisites).to include("db:seed")
104
124
  end
@@ -113,6 +133,7 @@ describe "db:setup" do
113
133
 
114
134
  it "works" do
115
135
  expect(Mongoid::Tasks::Database).to receive(:create_indexes)
136
+ expect(Mongoid::Tasks::Database).to receive(:create_collections)
116
137
  expect(Rails).to receive(:root).and_return(".")
117
138
  expect(Rails).to receive(:application).and_return(application)
118
139
  task.invoke
@@ -169,9 +190,14 @@ describe "db:test:prepare" do
169
190
  expect(task.prerequisites).to include("mongoid:create_indexes")
170
191
  end
171
192
 
193
+ it "calls mongoid:create_collections" do
194
+ expect(task.prerequisites).to include("mongoid:create_collections")
195
+ end
196
+
172
197
  it "works" do
173
198
  expect(Rails).to receive(:application).and_return(application)
174
199
  expect(Mongoid::Tasks::Database).to receive(:create_indexes)
200
+ expect(Mongoid::Tasks::Database).to receive(:create_collections)
175
201
  task.invoke
176
202
  end
177
203
  end
@@ -200,6 +226,54 @@ describe "db:mongoid:create_indexes" do
200
226
  end
201
227
  end
202
228
 
229
+ describe "db:mongoid:create_collections" do
230
+ include_context "rake task"
231
+
232
+ it_behaves_like "create_collections"
233
+
234
+ it "calls load_models" do
235
+ expect(task.prerequisites).to include("load_models")
236
+ end
237
+
238
+ it "calls environment" do
239
+ expect(task.prerequisites).to include("environment")
240
+ end
241
+
242
+ context "when using rails task" do
243
+ include_context "rails rake task"
244
+
245
+ before do
246
+ expect(Rails).to receive(:application).and_return(application)
247
+ end
248
+
249
+ it_behaves_like "create_collections"
250
+ end
251
+ end
252
+
253
+ describe "db:mongoid:create_collections:force" do
254
+ include_context "rake task"
255
+
256
+ it_behaves_like "force create_collections"
257
+
258
+ it "calls load_models" do
259
+ expect(task.prerequisites).to include("load_models")
260
+ end
261
+
262
+ it "calls environment" do
263
+ expect(task.prerequisites).to include("environment")
264
+ end
265
+
266
+ context "when using rails task" do
267
+ include_context "rails rake task"
268
+
269
+ before do
270
+ expect(Rails).to receive(:application).and_return(application)
271
+ end
272
+
273
+ it_behaves_like "force create_collections"
274
+ end
275
+ end
276
+
203
277
  describe "db:mongoid:remove_undefined_indexes" do
204
278
  include_context "rake task"
205
279