mongoid 8.0.9 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) 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/Rakefile +18 -67
  6. data/lib/config/locales/en.yml +46 -14
  7. data/lib/mongoid/association/accessors.rb +3 -7
  8. data/lib/mongoid/association/builders.rb +1 -1
  9. data/lib/mongoid/association/eager_loadable.rb +0 -3
  10. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  11. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  12. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  14. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +6 -6
  15. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  16. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  17. data/lib/mongoid/association/macros.rb +0 -6
  18. data/lib/mongoid/association/nested/one.rb +40 -2
  19. data/lib/mongoid/association/proxy.rb +1 -1
  20. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  21. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  22. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  23. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
  24. data/lib/mongoid/association/reflections.rb +2 -2
  25. data/lib/mongoid/atomic.rb +7 -16
  26. data/lib/mongoid/attributes/dynamic.rb +1 -1
  27. data/lib/mongoid/attributes/nested.rb +2 -2
  28. data/lib/mongoid/attributes/processing.rb +5 -29
  29. data/lib/mongoid/attributes/projector.rb +1 -1
  30. data/lib/mongoid/attributes/readonly.rb +1 -1
  31. data/lib/mongoid/attributes.rb +8 -2
  32. data/lib/mongoid/changeable.rb +107 -5
  33. data/lib/mongoid/clients/storage_options.rb +2 -5
  34. data/lib/mongoid/clients/validators/storage.rb +1 -13
  35. data/lib/mongoid/collection_configurable.rb +58 -0
  36. data/lib/mongoid/composable.rb +2 -0
  37. data/lib/mongoid/config/defaults.rb +60 -0
  38. data/lib/mongoid/config/options.rb +0 -3
  39. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  40. data/lib/mongoid/config/validators.rb +1 -0
  41. data/lib/mongoid/config.rb +88 -27
  42. data/lib/mongoid/contextual/atomic.rb +1 -1
  43. data/lib/mongoid/contextual/memory.rb +233 -33
  44. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  45. data/lib/mongoid/contextual/mongo.rb +370 -133
  46. data/lib/mongoid/contextual/none.rb +162 -7
  47. data/lib/mongoid/contextual.rb +12 -0
  48. data/lib/mongoid/criteria/findable.rb +2 -2
  49. data/lib/mongoid/criteria/includable.rb +4 -3
  50. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -15
  51. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  52. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  53. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  54. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  55. data/lib/mongoid/criteria/queryable/selector.rb +1 -1
  56. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  57. data/lib/mongoid/criteria.rb +6 -5
  58. data/lib/mongoid/deprecable.rb +1 -2
  59. data/lib/mongoid/deprecation.rb +3 -3
  60. data/lib/mongoid/document.rb +1 -8
  61. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  62. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  63. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  64. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  65. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  66. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  67. data/lib/mongoid/errors.rb +4 -1
  68. data/lib/mongoid/extensions/hash.rb +2 -24
  69. data/lib/mongoid/extensions/object.rb +2 -2
  70. data/lib/mongoid/extensions/time.rb +2 -0
  71. data/lib/mongoid/fields/localized.rb +10 -0
  72. data/lib/mongoid/fields/standard.rb +10 -0
  73. data/lib/mongoid/fields.rb +59 -35
  74. data/lib/mongoid/findable.rb +27 -3
  75. data/lib/mongoid/interceptable.rb +6 -116
  76. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  77. data/lib/mongoid/matcher/type.rb +1 -1
  78. data/lib/mongoid/persistable/creatable.rb +1 -0
  79. data/lib/mongoid/persistable/deletable.rb +1 -1
  80. data/lib/mongoid/persistable/savable.rb +13 -1
  81. data/lib/mongoid/persistable/unsettable.rb +2 -2
  82. data/lib/mongoid/persistable/updatable.rb +51 -1
  83. data/lib/mongoid/persistable/upsertable.rb +20 -1
  84. data/lib/mongoid/persistable.rb +3 -0
  85. data/lib/mongoid/query_cache.rb +5 -1
  86. data/lib/mongoid/railties/database.rake +7 -2
  87. data/lib/mongoid/reloadable.rb +5 -3
  88. data/lib/mongoid/stateful.rb +22 -1
  89. data/lib/mongoid/tasks/database.rake +12 -0
  90. data/lib/mongoid/tasks/database.rb +20 -0
  91. data/lib/mongoid/timestamps/created.rb +1 -8
  92. data/lib/mongoid/traversable.rb +0 -12
  93. data/lib/mongoid/utils.rb +22 -0
  94. data/lib/mongoid/validatable/associated.rb +17 -98
  95. data/lib/mongoid/validatable/macros.rb +5 -5
  96. data/lib/mongoid/validatable.rb +4 -9
  97. data/lib/mongoid/version.rb +1 -1
  98. data/lib/mongoid/warnings.rb +17 -1
  99. data/lib/mongoid.rb +16 -3
  100. data/spec/integration/app_spec.rb +2 -2
  101. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +0 -40
  102. data/spec/integration/callbacks_spec.rb +99 -12
  103. data/spec/integration/discriminator_key_spec.rb +4 -5
  104. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  105. data/spec/mongoid/association/eager_spec.rb +2 -24
  106. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  107. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
  108. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  109. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +0 -4
  110. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  111. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  112. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +5 -27
  113. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
  114. data/spec/mongoid/association/syncable_spec.rb +1 -1
  115. data/spec/mongoid/association_spec.rb +0 -60
  116. data/spec/mongoid/attributes_spec.rb +3 -33
  117. data/spec/mongoid/changeable_spec.rb +299 -24
  118. data/spec/mongoid/clients_spec.rb +122 -13
  119. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  120. data/spec/mongoid/config/defaults_spec.rb +160 -0
  121. data/spec/mongoid/config_spec.rb +154 -27
  122. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  123. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  124. data/spec/mongoid/contextual/mongo_spec.rb +1009 -125
  125. data/spec/mongoid/contextual/none_spec.rb +49 -2
  126. data/spec/mongoid/copyable_spec.rb +2 -10
  127. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
  128. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  129. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  130. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  131. data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -76
  132. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  133. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  134. data/spec/mongoid/criteria_spec.rb +5 -9
  135. data/spec/mongoid/document_spec.rb +0 -27
  136. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  137. data/spec/mongoid/extensions/hash_spec.rb +3 -3
  138. data/spec/mongoid/extensions/time_spec.rb +8 -43
  139. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  140. data/spec/mongoid/fields/localized_spec.rb +46 -28
  141. data/spec/mongoid/fields_spec.rb +136 -77
  142. data/spec/mongoid/findable_spec.rb +391 -34
  143. data/spec/mongoid/indexable_spec.rb +16 -10
  144. data/spec/mongoid/interceptable_spec.rb +153 -442
  145. data/spec/mongoid/interceptable_spec_models.rb +111 -51
  146. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  147. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  148. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  149. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  150. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  151. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  152. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  153. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  154. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  155. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  156. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  157. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  158. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  159. data/spec/mongoid/persistence_context_spec.rb +7 -57
  160. data/spec/mongoid/query_cache_spec.rb +56 -61
  161. data/spec/mongoid/reloadable_spec.rb +24 -28
  162. data/spec/mongoid/scopable_spec.rb +70 -0
  163. data/spec/mongoid/serializable_spec.rb +23 -44
  164. data/spec/mongoid/stateful_spec.rb +122 -8
  165. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  166. data/spec/mongoid/tasks/database_spec.rb +127 -0
  167. data/spec/mongoid/timestamps/created_spec.rb +0 -23
  168. data/spec/mongoid/timestamps_spec.rb +9 -11
  169. data/spec/mongoid/touchable_spec.rb +277 -5
  170. data/spec/mongoid/touchable_spec_models.rb +3 -1
  171. data/spec/mongoid/traversable_spec.rb +9 -24
  172. data/spec/mongoid/validatable/associated_spec.rb +34 -27
  173. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  174. data/spec/mongoid_spec.rb +36 -10
  175. data/spec/shared/LICENSE +20 -0
  176. data/spec/shared/bin/get-mongodb-download-url +17 -0
  177. data/spec/shared/bin/s3-copy +45 -0
  178. data/spec/shared/bin/s3-upload +69 -0
  179. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  180. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  181. data/spec/shared/lib/mrss/constraints.rb +378 -0
  182. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  183. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  184. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  185. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  186. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  187. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  188. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  189. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  190. data/spec/shared/lib/mrss/utils.rb +37 -0
  191. data/spec/shared/share/Dockerfile.erb +321 -0
  192. data/spec/shared/share/haproxy-1.conf +16 -0
  193. data/spec/shared/share/haproxy-2.conf +17 -0
  194. data/spec/shared/shlib/config.sh +27 -0
  195. data/spec/shared/shlib/distro.sh +74 -0
  196. data/spec/shared/shlib/server.sh +416 -0
  197. data/spec/shared/shlib/set_env.sh +169 -0
  198. data/spec/spec_helper.rb +5 -0
  199. data/spec/support/immutable_ids.rb +118 -0
  200. data/spec/support/macros.rb +47 -15
  201. data/spec/support/models/artist.rb +0 -1
  202. data/spec/support/models/band.rb +1 -0
  203. data/spec/support/models/book.rb +1 -0
  204. data/spec/support/models/building.rb +2 -0
  205. data/spec/support/models/cover.rb +10 -0
  206. data/spec/support/models/name.rb +0 -10
  207. data/spec/support/models/person.rb +0 -1
  208. data/spec/support/models/product.rb +1 -0
  209. data.tar.gz.sig +0 -0
  210. metadata +746 -636
  211. metadata.gz.sig +2 -0
  212. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  213. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  214. data/spec/support/models/purse.rb +0 -9
@@ -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
 
@@ -4,6 +4,59 @@ require "spec_helper"
4
4
 
5
5
  describe "Mongoid::Tasks::Database" do
6
6
 
7
+ before(:all) do
8
+ module DatabaseSpec
9
+ class Measurement
10
+ include Mongoid::Document
11
+
12
+ field :timestamp, type: Time
13
+ field :temperature, type: Integer
14
+
15
+ embeds_many :comments
16
+
17
+ store_in collection: "measurement",
18
+ collection_options: {
19
+ capped: true, size: 10000
20
+ }
21
+ end
22
+
23
+ class Comment
24
+ include Mongoid::Document
25
+
26
+ field :content, type: String
27
+
28
+ embedded_in :measurement
29
+
30
+ store_in collection_options: {
31
+ capped: true, size: 10000
32
+ }
33
+ end
34
+
35
+ class Note
36
+ include Mongoid::Document
37
+
38
+ field :text
39
+
40
+ recursively_embeds_one
41
+
42
+ store_in collection_options: {
43
+ capped: true, size: 10000
44
+ }
45
+ end
46
+ end
47
+ end
48
+
49
+ after(:all) do
50
+ Mongoid.deregister_model(DatabaseSpec::Measurement)
51
+ DatabaseSpec.send(:remove_const, :Measurement)
52
+ Mongoid.deregister_model(DatabaseSpec::Comment)
53
+ DatabaseSpec.send(:remove_const, :Comment)
54
+ Mongoid.deregister_model(DatabaseSpec::Note)
55
+ DatabaseSpec.send(:remove_const, :Note)
56
+ Object.send(:remove_const, :DatabaseSpec)
57
+ end
58
+
59
+
7
60
  let(:logger) do
8
61
  double("logger").tap do |log|
9
62
  allow(log).to receive(:info)
@@ -18,6 +71,80 @@ describe "Mongoid::Tasks::Database" do
18
71
  [ User, Account, Address, Draft ]
19
72
  end
20
73
 
74
+ describe '.create_collections' do
75
+ context 'collection_options are specified' do
76
+ let(:models) do
77
+ [DatabaseSpec::Measurement]
78
+ end
79
+
80
+ after do
81
+ DatabaseSpec::Measurement.collection.drop
82
+ end
83
+
84
+ [true, false].each do |force|
85
+ context "when force is #{force}" do
86
+ it 'creates the collection' do
87
+ expect(DatabaseSpec::Measurement).to receive(:create_collection).once.with(force: force)
88
+ Mongoid::Tasks::Database.create_collections(models, force: force)
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ context 'collection_options are not specified' do
95
+ let(:models) do
96
+ [Person]
97
+ end
98
+
99
+ [true, false].each do |force|
100
+ context "when force is #{force}" do
101
+ it 'creates the collection' do
102
+ expect(Person).to receive(:create_collection).once.with(force: force)
103
+ Mongoid::Tasks::Database.create_collections(models, force: force)
104
+ end
105
+ end
106
+ end
107
+
108
+ context "when collection options is defined on embedded model" do
109
+
110
+ let(:models) do
111
+ [DatabaseSpec::Comment]
112
+ end
113
+
114
+ let(:logger) do
115
+ double("logger").tap do |log|
116
+ expect(log).to receive(:info).once.with(/MONGOID: collection options ignored on: .*, please define in the root model/)
117
+ end
118
+ end
119
+
120
+ before do
121
+ allow(Mongoid::Tasks::Database).to receive(:logger).and_return(logger)
122
+ end
123
+
124
+ it "does nothing, but logging" do
125
+ expect(DatabaseSpec::Comment).to receive(:create_collection).never
126
+ Mongoid::Tasks::Database.create_collections(models)
127
+ end
128
+ end
129
+
130
+ context "when collection options is defined on cyclic model" do
131
+
132
+ let(:models) do
133
+ [DatabaseSpec::Note]
134
+ end
135
+
136
+ after do
137
+ DatabaseSpec::Note.collection.drop
138
+ end
139
+
140
+ it "creates the collection" do
141
+ expect(DatabaseSpec::Note).to receive(:create_collection).once
142
+ Mongoid::Tasks::Database.create_collections(models)
143
+ end
144
+ end
145
+ end
146
+ end
147
+
21
148
  describe ".create_indexes" do
22
149
 
23
150
  let!(:klass) do
@@ -43,27 +43,4 @@ describe Mongoid::Timestamps::Created do
43
43
  expect(quiz.created_at).to be_within(10).of(Time.now.utc)
44
44
  end
45
45
  end
46
-
47
- context "when the document is destroyed" do
48
- let(:book) do
49
- Book.create!
50
- end
51
-
52
- before do
53
- Cover.before_save do
54
- destroy if title == "delete me"
55
- end
56
- end
57
-
58
- after do
59
- Cover.reset_callbacks(:save)
60
- end
61
-
62
- it "does not set the created_at timestamp" do
63
- book.covers << Cover.new(title: "delete me")
64
- expect {
65
- book.save
66
- }.not_to raise_error
67
- end
68
- end
69
46
  end
@@ -17,12 +17,7 @@ describe Mongoid::Timestamps do
17
17
 
18
18
  let(:time_zone) { "Pacific Time (US & Canada)" }
19
19
 
20
- around do |ex|
21
- z = Time.zone
22
- Time.zone = time_zone
23
- ex.run
24
- Time.zone = z
25
- end
20
+ time_zone_override "Pacific Time (US & Canada)"
26
21
 
27
22
  before do
28
23
  document.run_callbacks(:create)
@@ -77,17 +72,20 @@ describe Mongoid::Timestamps do
77
72
  context "when the document has changed with updated_at specified" do
78
73
 
79
74
  let(:document) do
80
- Dokument.new(created_at: Time.now.utc)
75
+ Dokument.create(created_at: Time.now.utc)
76
+ end
77
+
78
+ let(:expected_updated_at) do
79
+ DateTime.parse("2001-06-12")
81
80
  end
82
81
 
83
82
  before do
84
- document.new_record = false
85
- document.updated_at = DateTime.parse("2001-06-12")
83
+ document.updated_at = expected_updated_at
86
84
  end
87
85
 
88
86
  it "does not set updated at" do
89
- expect(document).to receive(:updated_at=).never
90
87
  document.save!
88
+ expect(document.reload.updated_at).to be == expected_updated_at
91
89
  end
92
90
  end
93
91
 
@@ -127,7 +125,7 @@ describe Mongoid::Timestamps do
127
125
  end
128
126
 
129
127
  # This section of tests describes the behavior of the updated_at field for
130
- # different updates on associations, as outlined in PR #5219.
128
+ # different updates on referenced associations, as outlined in PR #5219.
131
129
  describe "updated_at attribute" do
132
130
  let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
133
131
 
@@ -89,7 +89,7 @@ describe Mongoid::Touchable do
89
89
  end
90
90
  end
91
91
 
92
- shared_examples 'updates the parent when :touch is not set' do
92
+ shared_examples 'updates the parent when :touch is false' do
93
93
  it 'does not update updated_at on parent' do
94
94
  entrance
95
95
  update_time
@@ -130,7 +130,7 @@ describe Mongoid::Touchable do
130
130
 
131
131
  include_examples 'updates the child'
132
132
  include_examples 'updates the parent when :touch is true'
133
- include_examples 'updates the parent when :touch is not set'
133
+ include_examples 'updates the parent when :touch is false'
134
134
 
135
135
  context 'when also updating an additional field' do
136
136
  it 'persists the update to the additional field' do
@@ -587,7 +587,7 @@ describe Mongoid::Touchable do
587
587
 
588
588
  context "when the touch option is true" do
589
589
 
590
- shared_examples "updates the updated_at" do
590
+ shared_examples "updates the parent's updated_at" do
591
591
 
592
592
  let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
593
593
 
@@ -624,19 +624,58 @@ describe Mongoid::Touchable do
624
624
  end
625
625
  end
626
626
 
627
+ shared_examples "updates the child's updated_at" do
628
+
629
+ let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
630
+
631
+ let(:update_time) do
632
+ Timecop.freeze(Time.at(Time.now.to_i) + 2)
633
+ end
634
+
635
+ after do
636
+ Timecop.return
637
+ end
638
+
639
+ let(:building) do
640
+ parent_cls.create!
641
+ end
642
+
643
+ let(:floor) do
644
+ building.floors.create!
645
+ end
646
+
647
+ before do
648
+ floor
649
+ update_time
650
+ floor.level = 9
651
+ floor.send(meth)
652
+ end
653
+
654
+ it "the parent is not nil" do
655
+ expect(floor.building).to_not be nil
656
+ end
657
+
658
+ it "updates the child's timestamp" do
659
+ floor.updated_at.should == update_time
660
+ floor.reload.updated_at.should == update_time
661
+ end
662
+ end
663
+
627
664
  [ :save!, :destroy, :touch].each do |meth|
628
665
  context "with #{meth} on referenced associations" do
629
666
  let(:parent_cls) { TouchableSpec::Referenced::Building }
630
667
  let(:meth) { meth }
631
668
 
632
- include_examples "updates the updated_at"
669
+ include_examples "updates the child's updated_at" unless meth == :destroy
670
+ include_examples "updates the parent's updated_at"
633
671
  end
634
672
 
635
673
  context "with #{meth} on embedded associations" do
636
674
  let(:parent_cls) { TouchableSpec::Embedded::Building }
637
675
  let(:meth) { meth }
638
676
 
639
- include_examples "updates the updated_at"
677
+ include_examples "updates the child's updated_at" unless meth == :destroy
678
+ include_examples "updates the parent's updated_at"
640
679
  end
641
680
  end
642
681
  end
@@ -701,4 +740,237 @@ describe Mongoid::Touchable do
701
740
  end
702
741
  end
703
742
  end
743
+
744
+ describe "when saving a document" do
745
+
746
+ let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
747
+
748
+ let(:update_time) do
749
+ Timecop.freeze(Time.at(Time.now.to_i) + 2)
750
+ end
751
+
752
+ after do
753
+ Timecop.return
754
+ end
755
+
756
+ context "when only using the root document" do
757
+
758
+ shared_examples "timeless is cleared" do
759
+ it "clears the timeless option" do
760
+ expect(doc.timeless?).to be false
761
+ end
762
+ end
763
+
764
+ shared_examples "touches the document" do
765
+ it "touches the document" do
766
+ expect(doc.created_at).to eq(start_time)
767
+ expect(doc.updated_at).to eq(start_time)
768
+ end
769
+ end
770
+
771
+ shared_examples "updates the document" do
772
+ it "updates the document" do
773
+ expect(doc.created_at).to eq(start_time)
774
+ expect(doc.updated_at).to eq(update_time)
775
+ end
776
+ end
777
+
778
+ let(:doc) { Dokument.new }
779
+
780
+ context "when saving a new document" do
781
+
782
+ context "when not passing a touch option" do
783
+
784
+ before do
785
+ doc.save!
786
+ end
787
+
788
+ include_examples "touches the document"
789
+ include_examples "timeless is cleared"
790
+ end
791
+
792
+ context "when passing touch: true" do
793
+
794
+ before do
795
+ doc.save!(touch: true)
796
+ end
797
+
798
+ include_examples "touches the document"
799
+ include_examples "timeless is cleared"
800
+ end
801
+
802
+ context "when passing touch: false" do
803
+
804
+ before do
805
+ doc.save!(touch: false)
806
+ end
807
+
808
+ include_examples "touches the document"
809
+ include_examples "timeless is cleared"
810
+ end
811
+ end
812
+
813
+ context "when updating a document" do
814
+ before do
815
+ doc.save!
816
+ doc.title = "title"
817
+ update_time
818
+ end
819
+
820
+ context "when not passing a touch option" do
821
+
822
+ before do
823
+ doc.save!
824
+ end
825
+
826
+ include_examples "updates the document"
827
+ include_examples "timeless is cleared"
828
+ end
829
+
830
+ context "when passing touch: true" do
831
+
832
+ before do
833
+ doc.save!(touch: true)
834
+ end
835
+
836
+ include_examples "updates the document"
837
+ include_examples "timeless is cleared"
838
+ end
839
+
840
+ context "when passing touch: false" do
841
+
842
+ before do
843
+ doc.save!(touch: false)
844
+ end
845
+
846
+ include_examples "touches the document"
847
+ include_examples "timeless is cleared"
848
+ end
849
+ end
850
+ end
851
+
852
+ context "when saving embedded associations with cascadable callbacks" do
853
+
854
+ shared_examples "timeless is cleared" do
855
+ it "clears the timeless option" do
856
+ expect(book.timeless?).to be false
857
+ expect(book.covers.first.timeless?).to be false
858
+ end
859
+ end
860
+
861
+ shared_examples "touches the document" do
862
+ it "touches the document" do
863
+ expect(book.created_at).to eq(start_time)
864
+ expect(book.updated_at).to eq(start_time)
865
+ end
866
+ end
867
+
868
+ shared_examples "updates the document" do
869
+ it "updates the document" do
870
+ expect(book.created_at).to eq(start_time)
871
+ expect(book.updated_at).to eq(update_time)
872
+ end
873
+ end
874
+
875
+ shared_examples "touches the children" do
876
+ it "touches the children" do
877
+ expect(book.covers.first.created_at).to eq(start_time)
878
+ expect(book.covers.first.updated_at).to eq(start_time)
879
+ end
880
+ end
881
+
882
+ shared_examples "updates the children" do
883
+ it "updates the children" do
884
+ expect(book.covers.first.created_at).to eq(start_time)
885
+ expect(book.covers.first.updated_at).to eq(update_time)
886
+ end
887
+ end
888
+
889
+ let(:book) do
890
+ Book.new(covers: [ cover ])
891
+ end
892
+
893
+ let(:cover) do
894
+ Cover.new
895
+ end
896
+
897
+ context "when saving a new document" do
898
+
899
+ context "when not passing a touch option" do
900
+
901
+ before do
902
+ book.save!
903
+ end
904
+
905
+ include_examples "touches the document"
906
+ include_examples "touches the children"
907
+ include_examples "timeless is cleared"
908
+ end
909
+
910
+ context "when passing touch: true" do
911
+
912
+ before do
913
+ book.save!(touch: true)
914
+ end
915
+
916
+ include_examples "touches the document"
917
+ include_examples "touches the children"
918
+ include_examples "timeless is cleared"
919
+ end
920
+
921
+ context "when passing touch: false" do
922
+
923
+ before do
924
+ book.save!(touch: false)
925
+ end
926
+
927
+ include_examples "touches the document"
928
+ include_examples "touches the children"
929
+ include_examples "timeless is cleared"
930
+ end
931
+ end
932
+
933
+ context "when updating a document" do
934
+ before do
935
+ book.save!
936
+ book.title = "title"
937
+ book.covers.first.title = "title"
938
+ update_time
939
+ end
940
+
941
+ context "when not passing a touch option" do
942
+
943
+ before do
944
+ book.save!
945
+ end
946
+
947
+ include_examples "updates the document"
948
+ include_examples "updates the children"
949
+ include_examples "timeless is cleared"
950
+ end
951
+
952
+ context "when passing touch: true" do
953
+
954
+ before do
955
+ book.save!(touch: true)
956
+ end
957
+
958
+ include_examples "updates the document"
959
+ include_examples "updates the children"
960
+ include_examples "timeless is cleared"
961
+ end
962
+
963
+ context "when passing touch: false" do
964
+
965
+ before do
966
+ book.save!(touch: false)
967
+ end
968
+
969
+ include_examples "touches the document"
970
+ include_examples "touches the children"
971
+ include_examples "timeless is cleared"
972
+ end
973
+ end
974
+ end
975
+ end
704
976
  end
@@ -6,6 +6,8 @@ module TouchableSpec
6
6
  include Mongoid::Document
7
7
  include Mongoid::Timestamps
8
8
 
9
+ field :title, type: String
10
+
9
11
  embeds_many :entrances, class_name: "TouchableSpec::Embedded::Entrance"
10
12
  embeds_many :floors, class_name: "TouchableSpec::Embedded::Floor"
11
13
  end
@@ -14,7 +16,7 @@ module TouchableSpec
14
16
  include Mongoid::Document
15
17
  include Mongoid::Timestamps
16
18
 
17
- embedded_in :building, class_name: "TouchableSpec::Embedded::Building"
19
+ embedded_in :building, touch: false, class_name: "TouchableSpec::Embedded::Building"
18
20
 
19
21
  field :last_used_at, type: Time
20
22
  end