mongoid 8.0.10 → 8.1.0

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 (212) 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 +6 -23
  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 -6
  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 +42 -55
  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/building.rb +2 -0
  204. data/spec/support/models/name.rb +0 -10
  205. data/spec/support/models/person.rb +0 -1
  206. data/spec/support/models/product.rb +1 -0
  207. data.tar.gz.sig +0 -0
  208. metadata +745 -637
  209. metadata.gz.sig +2 -0
  210. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  211. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  212. data/spec/support/models/purse.rb +0 -9
@@ -1,19 +1,13 @@
1
1
  module InterceptableSpec
2
2
  class CallbackRegistry
3
- def initialize(only: [])
3
+ def initialize
4
4
  @calls = []
5
- @only = only
6
5
  end
7
6
 
8
7
  def record_call(cls, cb)
9
- return unless @only.empty? || @only.any? { |pat| pat == cb }
10
8
  @calls << [cls, cb]
11
9
  end
12
10
 
13
- def reset!
14
- @calls.clear
15
- end
16
-
17
11
  attr_reader :calls
18
12
  end
19
13
 
@@ -21,8 +15,6 @@ module InterceptableSpec
21
15
  extend ActiveSupport::Concern
22
16
 
23
17
  included do
24
- field :name, type: String
25
-
26
18
  %i(
27
19
  validation save create update
28
20
  ).each do |what|
@@ -42,128 +34,196 @@ module InterceptableSpec
42
34
  end
43
35
  end
44
36
  end
37
+ end
45
38
 
46
- attr_accessor :callback_registry
39
+ class CbHasOneParent
40
+ include Mongoid::Document
47
41
 
48
- def initialize(callback_registry, *args, **kwargs)
42
+ has_one :child, autosave: true, class_name: "CbHasOneChild", inverse_of: :parent
43
+
44
+ def initialize(callback_registry)
49
45
  @callback_registry = callback_registry
50
- super(*args, **kwargs)
46
+ super()
51
47
  end
52
- end
53
48
 
54
- module RootInsertable
49
+ attr_accessor :callback_registry
50
+
55
51
  def insert_as_root
56
52
  @callback_registry&.record_call(self.class, :insert_into_database)
57
53
  super
58
54
  end
59
- end
60
55
 
61
- class CbHasOneParent
62
- include Mongoid::Document
63
56
  include CallbackTracking
64
- include RootInsertable
65
-
66
- has_one :child, autosave: true, class_name: "CbHasOneChild", inverse_of: :parent
67
57
  end
68
58
 
69
59
  class CbHasOneChild
70
60
  include Mongoid::Document
71
- include CallbackTracking
72
61
 
73
62
  belongs_to :parent, class_name: "CbHasOneParent", inverse_of: :child
63
+
64
+ def initialize(callback_registry)
65
+ @callback_registry = callback_registry
66
+ super()
67
+ end
68
+
69
+ attr_accessor :callback_registry
70
+
71
+ include CallbackTracking
74
72
  end
75
73
 
76
74
  class CbHasManyParent
77
75
  include Mongoid::Document
78
- include CallbackTracking
79
- include RootInsertable
80
76
 
81
77
  has_many :children, autosave: true, class_name: "CbHasManyChild", inverse_of: :parent
78
+
79
+ def initialize(callback_registry)
80
+ @callback_registry = callback_registry
81
+ super()
82
+ end
83
+
84
+ attr_accessor :callback_registry
85
+
86
+ def insert_as_root
87
+ @callback_registry&.record_call(self.class, :insert_into_database)
88
+ super
89
+ end
90
+
91
+ include CallbackTracking
82
92
  end
83
93
 
84
94
  class CbHasManyChild
85
95
  include Mongoid::Document
86
- include CallbackTracking
87
96
 
88
97
  belongs_to :parent, class_name: "CbHasManyParent", inverse_of: :children
98
+
99
+ def initialize(callback_registry)
100
+ @callback_registry = callback_registry
101
+ super()
102
+ end
103
+
104
+ attr_accessor :callback_registry
105
+
106
+ include CallbackTracking
89
107
  end
90
108
 
91
109
  class CbEmbedsOneParent
92
110
  include Mongoid::Document
93
- include CallbackTracking
94
- include RootInsertable
95
111
 
96
112
  field :name
97
113
 
98
114
  embeds_one :child, cascade_callbacks: true, class_name: "CbEmbedsOneChild", inverse_of: :parent
115
+
116
+ def initialize(callback_registry)
117
+ @callback_registry = callback_registry
118
+ super()
119
+ end
120
+
121
+ attr_accessor :callback_registry
122
+
123
+ def insert_as_root
124
+ @callback_registry&.record_call(self.class, :insert_into_database)
125
+ super
126
+ end
127
+
128
+ include CallbackTracking
99
129
  end
100
130
 
101
131
  class CbEmbedsOneChild
102
132
  include Mongoid::Document
103
- include CallbackTracking
104
133
 
105
134
  field :age
106
135
 
107
136
  embedded_in :parent, class_name: "CbEmbedsOneParent", inverse_of: :child
137
+
138
+ def initialize(callback_registry)
139
+ @callback_registry = callback_registry
140
+ super()
141
+ end
142
+
143
+ attr_accessor :callback_registry
144
+
145
+ include CallbackTracking
108
146
  end
109
147
 
110
148
  class CbEmbedsManyParent
111
149
  include Mongoid::Document
112
- include CallbackTracking
113
- include RootInsertable
114
150
 
115
151
  embeds_many :children, cascade_callbacks: true, class_name: "CbEmbedsManyChild", inverse_of: :parent
152
+
153
+ def initialize(callback_registry)
154
+ @callback_registry = callback_registry
155
+ super()
156
+ end
157
+
158
+ attr_accessor :callback_registry
159
+
160
+ def insert_as_root
161
+ @callback_registry&.record_call(self.class, :insert_into_database)
162
+ super
163
+ end
164
+
165
+ include CallbackTracking
116
166
  end
117
167
 
118
168
  class CbEmbedsManyChild
119
169
  include Mongoid::Document
120
- include CallbackTracking
121
170
 
122
171
  embedded_in :parent, class_name: "CbEmbedsManyParent", inverse_of: :children
172
+
173
+ def initialize(callback_registry)
174
+ @callback_registry = callback_registry
175
+ super()
176
+ end
177
+
178
+ attr_accessor :callback_registry
179
+
180
+ include CallbackTracking
123
181
  end
124
182
 
125
183
  class CbParent
126
184
  include Mongoid::Document
127
- include CallbackTracking
185
+
186
+ def initialize(callback_registry)
187
+ @callback_registry = callback_registry
188
+ super()
189
+ end
190
+
191
+ attr_accessor :callback_registry
128
192
 
129
193
  embeds_many :cb_children
130
194
  embeds_many :cb_cascaded_children, cascade_callbacks: true
131
- embeds_many :cb_cascaded_nodes, cascade_callbacks: true, as: :parent
195
+
196
+ include CallbackTracking
132
197
  end
133
198
 
134
199
  class CbChild
135
200
  include Mongoid::Document
136
- include CallbackTracking
137
201
 
138
202
  embedded_in :cb_parent
203
+
204
+ def initialize(callback_registry, options)
205
+ @callback_registry = callback_registry
206
+ super(options)
207
+ end
208
+
209
+ attr_accessor :callback_registry
210
+
211
+ include CallbackTracking
139
212
  end
140
213
 
141
214
  class CbCascadedChild
142
215
  include Mongoid::Document
143
- include CallbackTracking
144
216
 
145
217
  embedded_in :cb_parent
146
218
 
147
- before_save :test_mongoid_state
148
-
149
- private
150
-
151
- # Helps test that cascading child callbacks have access to the Mongoid
152
- # state objects; if the implementation uses fiber-local (instead of truly
153
- # thread-local) variables, the related tests will fail because the
154
- # cascading child callbacks use fibers to linearize the recursion.
155
- def test_mongoid_state
156
- Mongoid::Threaded.stack('interceptable').push(self)
219
+ def initialize(callback_registry, options)
220
+ @callback_registry = callback_registry
221
+ super(options)
157
222
  end
158
- end
159
223
 
160
- class CbCascadedNode
161
- include Mongoid::Document
162
- include CallbackTracking
163
-
164
- embedded_in :parent, polymorphic: true
224
+ attr_accessor :callback_registry
165
225
 
166
- embeds_many :cb_cascaded_nodes, cascade_callbacks: true, as: :parent
226
+ include CallbackTracking
167
227
  end
168
228
  end
169
229
 
@@ -12,14 +12,34 @@ describe Mongoid::Persistable::Deletable do
12
12
 
13
13
  context "when deleting a readonly document" do
14
14
 
15
- let(:from_db) do
16
- Person.only(:_id).first
15
+ context "when legacy_attributes is true" do
16
+ config_override :legacy_readonly, true
17
+
18
+ let(:from_db) do
19
+ Person.only(:_id).first
20
+ end
21
+
22
+ it "raises an error" do
23
+ expect(from_db.readonly?).to be true
24
+ expect {
25
+ from_db.delete
26
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
27
+ end
17
28
  end
18
29
 
19
- it "raises an error" do
20
- expect {
21
- from_db.delete
22
- }.to raise_error(Mongoid::Errors::ReadonlyDocument)
30
+ context "when legacy_attributes is false" do
31
+ config_override :legacy_readonly, false
32
+
33
+ let(:from_db) do
34
+ Person.first.tap(&:readonly!)
35
+ end
36
+
37
+ it "raises an error" do
38
+ expect(from_db.readonly?).to be true
39
+ expect {
40
+ from_db.delete
41
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
42
+ end
23
43
  end
24
44
  end
25
45
 
@@ -12,14 +12,34 @@ describe Mongoid::Persistable::Destroyable do
12
12
 
13
13
  context "when destroying a readonly document" do
14
14
 
15
- let(:from_db) do
16
- Person.only(:_id).first
15
+ context "when legacy_attributes is true" do
16
+ config_override :legacy_readonly, true
17
+
18
+ let(:from_db) do
19
+ Person.only(:_id).first
20
+ end
21
+
22
+ it "raises an error" do
23
+ expect(from_db.readonly?).to be true
24
+ expect {
25
+ from_db.destroy
26
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
27
+ end
17
28
  end
18
29
 
19
- it "raises an error" do
20
- expect {
21
- from_db.destroy
22
- }.to raise_error(Mongoid::Errors::ReadonlyDocument)
30
+ context "when legacy_attributes is false" do
31
+ config_override :legacy_readonly, false
32
+
33
+ let(:from_db) do
34
+ Person.first.tap(&:readonly!)
35
+ end
36
+
37
+ it "raises an error" do
38
+ expect(from_db.readonly?).to be true
39
+ expect {
40
+ from_db.destroy
41
+ }.to raise_error(Mongoid::Errors::ReadonlyDocument)
42
+ end
23
43
  end
24
44
  end
25
45
 
@@ -237,5 +237,42 @@ describe Mongoid::Persistable::Incrementable do
237
237
  end
238
238
  end
239
239
  end
240
+
241
+ context "when executing on a readonly document" do
242
+
243
+ let(:person) do
244
+ Person.create!(age: 10, score: 100)
245
+ end
246
+
247
+ context "when legacy_readonly is true" do
248
+ config_override :legacy_readonly, true
249
+
250
+ before do
251
+ person.__selected_fields = { "age" => 1, "score" => 1 }
252
+ end
253
+
254
+ it "persists the changes" do
255
+ expect(person).to be_readonly
256
+ person.inc(age: 15, score: 2)
257
+ expect(person.age).to eq(25)
258
+ expect(person.score).to eq(102)
259
+ end
260
+ end
261
+
262
+ context "when legacy_readonly is false" do
263
+ config_override :legacy_readonly, false
264
+
265
+ before do
266
+ person.readonly!
267
+ end
268
+
269
+ it "raises a ReadonlyDocument error" do
270
+ expect(person).to be_readonly
271
+ expect do
272
+ person.inc(age: 15, score: 2)
273
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
274
+ end
275
+ end
276
+ end
240
277
  end
241
278
  end
@@ -155,5 +155,42 @@ describe Mongoid::Persistable::Logical do
155
155
  end
156
156
  end
157
157
  end
158
+
159
+ context "when executing on a readonly document" do
160
+
161
+ let(:person) do
162
+ Person.create!(age: 10, score: 100)
163
+ end
164
+
165
+ context "when legacy_readonly is true" do
166
+ config_override :legacy_readonly, true
167
+
168
+ before do
169
+ person.__selected_fields = { "age" => 1, "score" => 1 }
170
+ end
171
+
172
+ it "persists the changes" do
173
+ expect(person).to be_readonly
174
+ person.bit(age: { and: 6 }, score: { or: 122 })
175
+ expect(person.age).to eq(2)
176
+ expect(person.score).to eq(126)
177
+ end
178
+ end
179
+
180
+ context "when legacy_readonly is false" do
181
+ config_override :legacy_readonly, false
182
+
183
+ before do
184
+ person.readonly!
185
+ end
186
+
187
+ it "raises a ReadonlyDocument error" do
188
+ expect(person).to be_readonly
189
+ expect do
190
+ person.bit(age: { and: 6 }, score: { or: 122 })
191
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
192
+ end
193
+ end
194
+ end
158
195
  end
159
196
  end
@@ -127,5 +127,41 @@ describe Mongoid::Persistable::Poppable do
127
127
  end
128
128
  end
129
129
  end
130
+
131
+ context "when executing on a readonly document" do
132
+
133
+ let(:person) do
134
+ Person.create!(test_array: [1, 2, 3])
135
+ end
136
+
137
+ context "when legacy_readonly is true" do
138
+ config_override :legacy_readonly, true
139
+
140
+ before do
141
+ person.__selected_fields = { "test_array" => 1 }
142
+ end
143
+
144
+ it "persists the changes" do
145
+ expect(person).to be_readonly
146
+ person.pop(test_array: 1)
147
+ expect(person.test_array).to eq([ 1, 2 ])
148
+ end
149
+ end
150
+
151
+ context "when legacy_readonly is false" do
152
+ config_override :legacy_readonly, false
153
+
154
+ before do
155
+ person.readonly!
156
+ end
157
+
158
+ it "raises a ReadonlyDocument error" do
159
+ expect(person).to be_readonly
160
+ expect do
161
+ person.pop(test_array: 1)
162
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
163
+ end
164
+ end
165
+ end
130
166
  end
131
167
  end
@@ -127,6 +127,42 @@ describe Mongoid::Persistable::Pullable do
127
127
  end
128
128
  end
129
129
  end
130
+
131
+ context "when executing on a readonly document" do
132
+
133
+ let(:person) do
134
+ Person.create!(test_array: [ 1, 1, 2, 3 ])
135
+ end
136
+
137
+ context "when legacy_readonly is true" do
138
+ config_override :legacy_readonly, true
139
+
140
+ before do
141
+ person.__selected_fields = { "test_array" => 1 }
142
+ end
143
+
144
+ it "persists the changes" do
145
+ expect(person).to be_readonly
146
+ person.pull(test_array: 1)
147
+ expect(person.test_array).to eq([ 2, 3 ])
148
+ end
149
+ end
150
+
151
+ context "when legacy_readonly is false" do
152
+ config_override :legacy_readonly, false
153
+
154
+ before do
155
+ person.readonly!
156
+ end
157
+
158
+ it "raises a ReadonlyDocument error" do
159
+ expect(person).to be_readonly
160
+ expect do
161
+ person.pull(test_array: 1)
162
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
163
+ end
164
+ end
165
+ end
130
166
  end
131
167
 
132
168
  describe "#pull_all" do
@@ -254,5 +290,41 @@ describe Mongoid::Persistable::Pullable do
254
290
  end
255
291
  end
256
292
  end
293
+
294
+ context "when executing on a readonly document" do
295
+
296
+ let(:person) do
297
+ Person.create!(test_array: [ 1, 1, 2, 3, 4 ])
298
+ end
299
+
300
+ context "when legacy_readonly is true" do
301
+ config_override :legacy_readonly, true
302
+
303
+ before do
304
+ person.__selected_fields = { "test_array" => 1 }
305
+ end
306
+
307
+ it "persists the changes" do
308
+ expect(person).to be_readonly
309
+ person.pull_all(test_array: [ 1, 2 ])
310
+ expect(person.test_array).to eq([ 3, 4 ])
311
+ end
312
+ end
313
+
314
+ context "when legacy_readonly is false" do
315
+ config_override :legacy_readonly, false
316
+
317
+ before do
318
+ person.readonly!
319
+ end
320
+
321
+ it "raises a ReadonlyDocument error" do
322
+ expect(person).to be_readonly
323
+ expect do
324
+ person.pull_all(test_array: [ 1, 2 ])
325
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
326
+ end
327
+ end
328
+ end
257
329
  end
258
330
  end
@@ -204,6 +204,42 @@ describe Mongoid::Persistable::Pushable do
204
204
  end
205
205
  end
206
206
  end
207
+
208
+ context "when executing on a readonly document" do
209
+
210
+ let(:person) do
211
+ Person.create!(test_array: [ 1, 2, 3 ])
212
+ end
213
+
214
+ context "when legacy_readonly is true" do
215
+ config_override :legacy_readonly, true
216
+
217
+ before do
218
+ person.__selected_fields = { "test_array" => 1 }
219
+ end
220
+
221
+ it "persists the changes" do
222
+ expect(person).to be_readonly
223
+ person.add_to_set(test_array: [ 1, 4 ])
224
+ expect(person.test_array).to eq([ 1, 2, 3, 4 ])
225
+ end
226
+ end
227
+
228
+ context "when legacy_readonly is false" do
229
+ config_override :legacy_readonly, false
230
+
231
+ before do
232
+ person.readonly!
233
+ end
234
+
235
+ it "raises a ReadonlyDocument error" do
236
+ expect(person).to be_readonly
237
+ expect do
238
+ person.add_to_set(test_array: [ 1, 4 ])
239
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
240
+ end
241
+ end
242
+ end
207
243
  end
208
244
 
209
245
  describe "#push" do
@@ -349,5 +385,41 @@ describe Mongoid::Persistable::Pushable do
349
385
  end
350
386
  end
351
387
  end
388
+
389
+ context "when executing on a readonly document" do
390
+
391
+ let(:person) do
392
+ Person.create!(test_array: [ 1, 2, 3 ])
393
+ end
394
+
395
+ context "when legacy_readonly is true" do
396
+ config_override :legacy_readonly, true
397
+
398
+ before do
399
+ person.__selected_fields = { "test_array" => 1 }
400
+ end
401
+
402
+ it "persists the changes" do
403
+ expect(person).to be_readonly
404
+ person.push(test_array: [ 1, 4 ])
405
+ expect(person.test_array).to eq([ 1, 2, 3, 1, 4 ])
406
+ end
407
+ end
408
+
409
+ context "when legacy_readonly is false" do
410
+ config_override :legacy_readonly, false
411
+
412
+ before do
413
+ person.readonly!
414
+ end
415
+
416
+ it "raises a ReadonlyDocument error" do
417
+ expect(person).to be_readonly
418
+ expect do
419
+ person.push(test_array: [ 1, 4 ])
420
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
421
+ end
422
+ end
423
+ end
352
424
  end
353
425
  end
@@ -147,5 +147,41 @@ describe Mongoid::Persistable::Renamable do
147
147
  end
148
148
  end
149
149
  end
150
+
151
+ context "when executing on a readonly document" do
152
+
153
+ let(:person) do
154
+ Person.create!(title: "sir")
155
+ end
156
+
157
+ context "when legacy_readonly is true" do
158
+ config_override :legacy_readonly, true
159
+
160
+ before do
161
+ person.__selected_fields = { "test_array" => 1 }
162
+ end
163
+
164
+ it "persists the changes" do
165
+ expect(person).to be_readonly
166
+ person.rename title: :salutation
167
+ expect(person.reload.salutation).to eq("sir")
168
+ end
169
+ end
170
+
171
+ context "when legacy_readonly is false" do
172
+ config_override :legacy_readonly, false
173
+
174
+ before do
175
+ person.readonly!
176
+ end
177
+
178
+ it "raises a ReadonlyDocument error" do
179
+ expect(person).to be_readonly
180
+ expect do
181
+ person.rename(title: :salutation)
182
+ end.to raise_error(Mongoid::Errors::ReadonlyDocument)
183
+ end
184
+ end
185
+ end
150
186
  end
151
187
  end