mongoid 5.4.1 → 6.0.0.beta

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 (264) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +23 -16
  5. data/lib/mongoid.rb +4 -9
  6. data/lib/mongoid/atomic.rb +1 -1
  7. data/lib/mongoid/atomic/modifiers.rb +8 -12
  8. data/lib/mongoid/attributes.rb +9 -11
  9. data/lib/mongoid/attributes/dynamic.rb +5 -6
  10. data/lib/mongoid/attributes/nested.rb +1 -1
  11. data/lib/mongoid/attributes/processing.rb +4 -0
  12. data/lib/mongoid/attributes/readonly.rb +22 -0
  13. data/lib/mongoid/cacheable.rb +36 -0
  14. data/lib/mongoid/changeable.rb +37 -1
  15. data/lib/mongoid/clients.rb +0 -63
  16. data/lib/mongoid/clients/factory.rb +0 -2
  17. data/lib/mongoid/clients/options.rb +54 -249
  18. data/lib/mongoid/clients/storage_options.rb +1 -69
  19. data/lib/mongoid/composable.rb +26 -2
  20. data/lib/mongoid/config.rb +1 -1
  21. data/lib/mongoid/config/options.rb +1 -1
  22. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -0
  23. data/lib/mongoid/contextual/atomic.rb +6 -9
  24. data/lib/mongoid/contextual/geo_near.rb +2 -3
  25. data/lib/mongoid/contextual/map_reduce.rb +97 -24
  26. data/lib/mongoid/contextual/memory.rb +7 -4
  27. data/lib/mongoid/contextual/mongo.rb +63 -54
  28. data/lib/mongoid/contextual/none.rb +2 -2
  29. data/lib/mongoid/copyable.rb +19 -19
  30. data/lib/mongoid/criteria.rb +5 -4
  31. data/lib/mongoid/criteria/findable.rb +2 -3
  32. data/lib/mongoid/criteria/includable.rb +63 -16
  33. data/lib/mongoid/criteria/marshalable.rb +2 -2
  34. data/lib/mongoid/criteria/modifiable.rb +17 -1
  35. data/lib/mongoid/criteria/options.rb +25 -0
  36. data/lib/mongoid/criteria/queryable.rb +86 -0
  37. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  38. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  39. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  40. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  41. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  42. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  43. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  44. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  45. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  47. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  48. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  49. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +45 -0
  50. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  51. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  52. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  53. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  54. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  55. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  56. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  57. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  58. data/lib/mongoid/criteria/queryable/mergeable.rb +271 -0
  59. data/lib/mongoid/criteria/queryable/optional.rb +411 -0
  60. data/lib/mongoid/criteria/queryable/options.rb +136 -0
  61. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  62. data/lib/mongoid/criteria/queryable/selectable.rb +662 -0
  63. data/lib/mongoid/criteria/queryable/selector.rb +196 -0
  64. data/lib/mongoid/criteria/queryable/smash.rb +103 -0
  65. data/lib/mongoid/document.rb +9 -23
  66. data/lib/mongoid/errors.rb +2 -1
  67. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  68. data/lib/mongoid/errors/delete_restriction.rb +2 -2
  69. data/lib/mongoid/errors/invalid_field.rb +2 -2
  70. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  71. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  72. data/lib/mongoid/errors/inverse_not_found.rb +1 -1
  73. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  74. data/lib/mongoid/evolvable.rb +1 -1
  75. data/lib/mongoid/extensions.rb +0 -5
  76. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  77. data/lib/mongoid/extensions/date.rb +4 -1
  78. data/lib/mongoid/extensions/hash.rb +2 -3
  79. data/lib/mongoid/extensions/object.rb +2 -2
  80. data/lib/mongoid/extensions/string.rb +4 -3
  81. data/lib/mongoid/extensions/time.rb +5 -2
  82. data/lib/mongoid/factory.rb +1 -0
  83. data/lib/mongoid/fields/foreign_key.rb +2 -2
  84. data/lib/mongoid/fields/localized.rb +3 -8
  85. data/lib/mongoid/fields/validators/macro.rb +18 -0
  86. data/lib/mongoid/findable.rb +3 -3
  87. data/lib/mongoid/indexable.rb +17 -16
  88. data/lib/mongoid/indexable/specification.rb +1 -1
  89. data/lib/mongoid/indexable/validators/options.rb +1 -2
  90. data/lib/mongoid/interceptable.rb +6 -17
  91. data/lib/mongoid/loggable.rb +1 -1
  92. data/lib/mongoid/matchable.rb +3 -10
  93. data/lib/mongoid/matchable/gt.rb +2 -0
  94. data/lib/mongoid/matchable/gte.rb +2 -0
  95. data/lib/mongoid/matchable/lt.rb +2 -0
  96. data/lib/mongoid/matchable/lte.rb +2 -0
  97. data/lib/mongoid/persistable.rb +6 -5
  98. data/lib/mongoid/persistable/creatable.rb +2 -0
  99. data/lib/mongoid/persistable/deletable.rb +7 -3
  100. data/lib/mongoid/persistable/settable.rb +3 -16
  101. data/lib/mongoid/persistable/updatable.rb +10 -12
  102. data/lib/mongoid/persistence_context.rb +216 -0
  103. data/lib/mongoid/query_cache.rb +5 -30
  104. data/lib/mongoid/relations/accessors.rb +6 -2
  105. data/lib/mongoid/relations/auto_save.rb +12 -4
  106. data/lib/mongoid/relations/bindings/embedded/in.rb +4 -0
  107. data/lib/mongoid/relations/bindings/embedded/many.rb +8 -1
  108. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -0
  109. data/lib/mongoid/relations/bindings/referenced/many.rb +4 -0
  110. data/lib/mongoid/relations/builders.rb +2 -2
  111. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  112. data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
  113. data/lib/mongoid/relations/conversions.rb +1 -1
  114. data/lib/mongoid/relations/counter_cache.rb +28 -18
  115. data/lib/mongoid/relations/eager.rb +19 -7
  116. data/lib/mongoid/relations/eager/base.rb +5 -5
  117. data/lib/mongoid/relations/embedded/batchable.rb +9 -33
  118. data/lib/mongoid/relations/embedded/in.rb +16 -2
  119. data/lib/mongoid/relations/embedded/many.rb +23 -8
  120. data/lib/mongoid/relations/embedded/one.rb +17 -2
  121. data/lib/mongoid/relations/macros.rb +9 -2
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/nested_builder.rb +1 -1
  124. data/lib/mongoid/relations/options.rb +2 -2
  125. data/lib/mongoid/relations/proxy.rb +2 -33
  126. data/lib/mongoid/relations/referenced/in.rb +23 -11
  127. data/lib/mongoid/relations/referenced/many.rb +24 -16
  128. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  129. data/lib/mongoid/relations/referenced/one.rb +17 -1
  130. data/lib/mongoid/relations/reflections.rb +3 -5
  131. data/lib/mongoid/relations/touchable.rb +1 -1
  132. data/lib/mongoid/reloadable.rb +1 -1
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +2 -3
  135. data/lib/mongoid/tasks/database.rb +1 -2
  136. data/lib/mongoid/threaded.rb +4 -4
  137. data/lib/mongoid/traversable.rb +1 -1
  138. data/lib/mongoid/validatable.rb +1 -1
  139. data/lib/mongoid/validatable/macros.rb +2 -4
  140. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  141. data/lib/mongoid/version.rb +1 -1
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -7
  143. data/spec/app/models/album.rb +5 -1
  144. data/spec/app/models/artist.rb +21 -0
  145. data/spec/app/models/band.rb +0 -1
  146. data/spec/app/models/church.rb +0 -2
  147. data/spec/app/models/ordered_post.rb +5 -0
  148. data/spec/app/models/oscar.rb +1 -2
  149. data/spec/app/models/person.rb +3 -1
  150. data/spec/app/models/post.rb +0 -1
  151. data/spec/app/models/princess.rb +2 -0
  152. data/spec/app/models/record.rb +1 -0
  153. data/spec/app/models/thing.rb +1 -1
  154. data/spec/config/mongoid.yml +1 -5
  155. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  156. data/spec/mongoid/atomic_spec.rb +17 -17
  157. data/spec/mongoid/attributes/nested_spec.rb +14 -14
  158. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  159. data/spec/mongoid/attributes_spec.rb +63 -0
  160. data/spec/mongoid/cacheable_spec.rb +112 -0
  161. data/spec/mongoid/changeable_spec.rb +58 -0
  162. data/spec/mongoid/clients/factory_spec.rb +3 -11
  163. data/spec/mongoid/clients/options_spec.rb +378 -96
  164. data/spec/mongoid/clients_spec.rb +207 -170
  165. data/spec/mongoid/composable_spec.rb +7 -0
  166. data/spec/mongoid/config_spec.rb +41 -21
  167. data/spec/mongoid/contextual/atomic_spec.rb +77 -343
  168. data/spec/mongoid/contextual/map_reduce_spec.rb +119 -111
  169. data/spec/mongoid/contextual/memory_spec.rb +56 -316
  170. data/spec/mongoid/contextual/mongo_spec.rb +104 -378
  171. data/spec/mongoid/copyable_spec.rb +8 -15
  172. data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
  173. data/spec/mongoid/criteria/options_spec.rb +29 -0
  174. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  175. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  176. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  177. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  178. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  179. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  180. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  181. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  182. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  183. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  184. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  185. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  186. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  187. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  188. data/spec/mongoid/{extensions/origin/regexp_raw_spec.rb → criteria/queryable/extensions/regexp_spec.rb} +21 -20
  189. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  190. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  191. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  192. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  193. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  194. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  195. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  196. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  197. data/spec/mongoid/criteria/queryable/optional_spec.rb +1786 -0
  198. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  199. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  200. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  201. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4159 -0
  202. data/spec/mongoid/criteria/queryable/selector_spec.rb +778 -0
  203. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  204. data/spec/mongoid/criteria_spec.rb +45 -63
  205. data/spec/mongoid/document_spec.rb +21 -88
  206. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  207. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  208. data/spec/mongoid/extensions/big_decimal_spec.rb +320 -18
  209. data/spec/mongoid/extensions/date_spec.rb +2 -6
  210. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  211. data/spec/mongoid/extensions/float_spec.rb +8 -1
  212. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  213. data/spec/mongoid/extensions/object_spec.rb +11 -0
  214. data/spec/mongoid/extensions/string_spec.rb +21 -0
  215. data/spec/mongoid/extensions/time_spec.rb +4 -8
  216. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  217. data/spec/mongoid/fields/localized_spec.rb +0 -91
  218. data/spec/mongoid/findable_spec.rb +46 -1
  219. data/spec/mongoid/indexable_spec.rb +6 -46
  220. data/spec/mongoid/interceptable_spec.rb +49 -10
  221. data/spec/mongoid/matchable/gt_spec.rb +11 -0
  222. data/spec/mongoid/matchable/gte_spec.rb +10 -0
  223. data/spec/mongoid/matchable/lt_spec.rb +11 -0
  224. data/spec/mongoid/matchable/lte_spec.rb +11 -0
  225. data/spec/mongoid/matchable_spec.rb +1 -51
  226. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  227. data/spec/mongoid/persistable/deletable_spec.rb +1 -1
  228. data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
  229. data/spec/mongoid/persistable/savable_spec.rb +30 -30
  230. data/spec/mongoid/persistable/settable_spec.rb +0 -185
  231. data/spec/mongoid/persistable/updatable_spec.rb +166 -5
  232. data/spec/mongoid/persistence_context_spec.rb +654 -0
  233. data/spec/mongoid/positional_spec.rb +10 -10
  234. data/spec/mongoid/query_cache_spec.rb +89 -65
  235. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  236. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  237. data/spec/mongoid/relations/builders_spec.rb +37 -10
  238. data/spec/mongoid/relations/counter_cache_spec.rb +64 -15
  239. data/spec/mongoid/relations/cyclic_spec.rb +0 -22
  240. data/spec/mongoid/relations/embedded/many_spec.rb +9 -41
  241. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  242. data/spec/mongoid/relations/macros_spec.rb +395 -7
  243. data/spec/mongoid/relations/proxy_spec.rb +3 -1
  244. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  245. data/spec/mongoid/relations/referenced/many_spec.rb +6 -29
  246. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +6 -29
  247. data/spec/mongoid/relations/reflections_spec.rb +9 -9
  248. data/spec/mongoid/reloadable_spec.rb +51 -0
  249. data/spec/mongoid/scopable_spec.rb +0 -12
  250. data/spec/mongoid/serializable_spec.rb +0 -50
  251. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  252. data/spec/mongoid/validatable/uniqueness_spec.rb +16 -9
  253. data/spec/mongoid/validatable_spec.rb +16 -0
  254. data/spec/spec_helper.rb +10 -10
  255. metadata +536 -479
  256. metadata.gz.sig +0 -0
  257. data/lib/mongoid/clients/thread_options.rb +0 -19
  258. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +0 -20
  259. data/lib/mongoid/extensions/decimal128.rb +0 -39
  260. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  261. data/lib/mongoid/matchable/regexp.rb +0 -27
  262. data/spec/app/models/post_genre.rb +0 -6
  263. data/spec/mongoid/extensions/decimal128_spec.rb +0 -44
  264. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
@@ -15,6 +15,8 @@ module Mongoid
15
15
  # @return [ true, false ] If a value exists.
16
16
  def matches?(value)
17
17
  determine(value, :>)
18
+ rescue ArgumentError
19
+ false
18
20
  end
19
21
  end
20
22
  end
@@ -15,6 +15,8 @@ module Mongoid
15
15
  # @return [ true, false ] If a value exists.
16
16
  def matches?(value)
17
17
  determine(value, :>=)
18
+ rescue ArgumentError
19
+ false
18
20
  end
19
21
  end
20
22
  end
@@ -15,6 +15,8 @@ module Mongoid
15
15
  # @return [ true, false ] If a value exists.
16
16
  def matches?(value)
17
17
  determine(value, :<)
18
+ rescue ArgumentError
19
+ false
18
20
  end
19
21
  end
20
22
  end
@@ -15,6 +15,8 @@ module Mongoid
15
15
  # @return [ true, false ] If a value exists.
16
16
  def matches?(value)
17
17
  determine(value, :<=)
18
+ rescue ArgumentError
19
+ false
18
20
  end
19
21
  end
20
22
  end
@@ -69,6 +69,8 @@ module Mongoid
69
69
  # @example Raise the validation error.
70
70
  # Person.fail_due_to_validation!(person)
71
71
  #
72
+ # @param [ Document ] document The document to fail.
73
+ #
72
74
  # @raise [ Errors::Validations ] The validation error.
73
75
  #
74
76
  # @since 4.0.0
@@ -81,6 +83,7 @@ module Mongoid
81
83
  # @example Raise the callback error.
82
84
  # Person.fail_due_to_callback!(person, :create!)
83
85
  #
86
+ # @param [ Document ] document The document to fail.
84
87
  # @param [ Symbol ] method The method being called.
85
88
  #
86
89
  # @raise [ Errors::Callback ] The callback error.
@@ -162,12 +165,10 @@ module Mongoid
162
165
  # @since 4.0.0
163
166
  def process_atomic_operations(operations)
164
167
  operations.each do |field, value|
165
- unless attribute_writable?(field)
166
- raise Errors::ReadonlyAttribute.new(field, value)
168
+ as_writable_attribute!(field, value) do |access|
169
+ yield(access, value)
170
+ remove_change(access)
167
171
  end
168
- normalized = database_field_name(field)
169
- yield(normalized, value)
170
- remove_change(normalized)
171
172
  end
172
173
  end
173
174
 
@@ -165,6 +165,8 @@ module Mongoid
165
165
  #
166
166
  # @param [ Hash, Array ] attributes The attributes to create with, or an
167
167
  # Array of multiple attributes for multiple documents.
168
+ # @param [ Hash ] options A mass-assignment protection options. Supports
169
+ # :as and :without_protection
168
170
  #
169
171
  # @return [ Document, Array<Document> ] The newly created document(s).
170
172
  #
@@ -135,9 +135,13 @@ module Mongoid
135
135
  # @return [ Integer ] The number of documents deleted.
136
136
  #
137
137
  # @since 1.0.0
138
- def delete_all(conditions = {})
139
- selector = hereditary? ? conditions.merge(_type: name) : conditions
140
- collection.find(selector).delete_many.deleted_count
138
+ def delete_all(conditions = nil)
139
+ selector = conditions || {}
140
+ selector.merge!(_type: name) if hereditary?
141
+ coll = collection
142
+ deleted = coll.find(selector).count
143
+ coll.find(selector).delete_many
144
+ deleted
141
145
  end
142
146
  end
143
147
  end
@@ -22,23 +22,10 @@ module Mongoid
22
22
  def set(setters)
23
23
  prepare_atomic_operation do |ops|
24
24
  process_atomic_operations(setters) do |field, value|
25
-
26
- field_and_value_hash = hasherizer(field.split('.'), value)
27
- field = field_and_value_hash.keys.first.to_s
28
-
29
- if fields[field] && fields[field].type == Hash && attributes.key?(field)
30
- merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
31
- value = attributes[field].merge(field_and_value_hash[field], &merger)
32
- process_attribute(field.to_s, value)
33
- else
34
- process_attribute(field.to_s, field_and_value_hash[field])
35
- end
36
-
37
- unless relations.include?(field.to_s)
38
- ops[atomic_attribute_name(field)] = attributes[field]
39
- end
25
+ process_attribute(field.to_s, value)
26
+ ops[atomic_attribute_name(field)] = attributes[field]
40
27
  end
41
- { "$set" => ops } unless ops.empty?
28
+ { "$set" => ops }
42
29
  end
43
30
  end
44
31
  end
@@ -24,17 +24,16 @@ module Mongoid
24
24
  #
25
25
  # @since 2.0.0
26
26
  def update_attribute(name, value)
27
- normalized = name.to_s
28
- unless attribute_writable?(normalized)
29
- raise Errors::ReadonlyAttribute.new(normalized, value)
30
- end
31
- setter = "#{normalized}="
32
- if respond_to?(setter)
33
- send(setter, value)
34
- else
35
- write_attribute(database_field_name(normalized), value)
27
+ as_writable_attribute!(name, value) do |access|
28
+ normalized = name.to_s
29
+ setter = "#{normalized}="
30
+ if respond_to?(setter)
31
+ send(setter, value)
32
+ else
33
+ write_attribute(access, value)
34
+ end
35
+ save(validate: false)
36
36
  end
37
- save(validate: false)
38
37
  end
39
38
 
40
39
  # Update the document attributes in the database.
@@ -135,11 +134,10 @@ module Mongoid
135
134
  #
136
135
  # @since 1.0.0
137
136
  def update_document(options = {})
138
- raise Errors::ReadonlyDocument.new(self.class) if readonly?
139
137
  prepare_update(options) do
140
138
  updates, conflicts = init_atomic_updates
141
139
  unless updates.empty?
142
- coll = _root.collection
140
+ coll = collection(_root)
143
141
  selector = atomic_selector
144
142
  coll.find(selector).update_one(positionally(selector, updates))
145
143
  conflicts.each_pair do |key, value|
@@ -0,0 +1,216 @@
1
+ module Mongoid
2
+
3
+ # Object encapsulating logic for setting/getting a collection and database name
4
+ # and a client with particular options to use when persisting models.
5
+ #
6
+ # @since 6.0.0
7
+ class PersistenceContext
8
+ extend Forwardable
9
+
10
+ # Delegate the cluster method to the client.
11
+ def_delegators :client, :cluster
12
+
13
+ # Delegate the storage options method to the object.
14
+ def_delegators :@object, :storage_options
15
+
16
+ # The options defining this persistence context.
17
+ #
18
+ # @return [ Hash ] The persistence context options.
19
+ #
20
+ # @since 6.0.0
21
+ attr_reader :options
22
+
23
+ # Extra options in addition to driver client options that determine the
24
+ # persistence context.
25
+ #
26
+ # @return [ Array<Symbol> ] The list of extra options besides client options
27
+ # that determine the persistence context.
28
+ #
29
+ # @since 6.0.0
30
+ EXTRA_OPTIONS = [ :client,
31
+ :collection
32
+ ].freeze
33
+
34
+ # The full list of valid persistence context options.
35
+ #
36
+ # @return [ Array<Symbol> ] The full list of options defining the persistence
37
+ # context.
38
+ #
39
+ # @since 6.0.0
40
+ VALID_OPTIONS = ( Mongo::Client::VALID_OPTIONS + EXTRA_OPTIONS ).freeze
41
+
42
+ # Initialize the persistence context object.
43
+ #
44
+ # @example Create a new persistence context.
45
+ # PersistenceContext.new(model, collection: 'other')
46
+ #
47
+ # @param [ Object ] parent The class or model instance for which a persistence context
48
+ # should be created.
49
+ # @param [ Hash ] opts The persistence context options.
50
+ #
51
+ # @since 6.0.0
52
+ def initialize(object, opts = {})
53
+ @object = object
54
+ set_options!(opts)
55
+ end
56
+
57
+ # Get the collection for this persistence context.
58
+ #
59
+ # @example Get the collection for this persistence context.
60
+ # context.collection
61
+ #
62
+ # @param [ Object ] parent The parent object whose collection name is used
63
+ # instead of this persistence context's collection name.
64
+ #
65
+ # @return [ Mongo::Collection ] The collection for this persistence
66
+ # context.
67
+ #
68
+ # @since 6.0.0
69
+ def collection(parent = nil)
70
+ name = parent ? parent.collection_name : collection_name
71
+ client[name.to_sym]
72
+ end
73
+
74
+ # Get the collection name for this persistence context.
75
+ #
76
+ # @example Get the collection name for this persistence context.
77
+ # context.collection_name
78
+ #
79
+ # @return [ String ] The collection name for this persistence
80
+ # context.
81
+ #
82
+ # @since 6.0.0
83
+ def collection_name
84
+ @collection_name ||= (__evaluate__(options[:collection] ||
85
+ storage_options[:collection]))
86
+ end
87
+
88
+ # Get the database name for this persistence context.
89
+ #
90
+ # @example Get the database name for this persistence context.
91
+ # context.database_name
92
+ #
93
+ # @return [ String ] The database name for this persistence
94
+ # context.
95
+ #
96
+ # @since 6.0.0
97
+ def database_name
98
+ __evaluate__(database_name_option) || client.database.name
99
+ end
100
+
101
+ # Get the client for this persistence context.
102
+ #
103
+ # @example Get the client for this persistence context.
104
+ # context.client
105
+ #
106
+ # @return [ Mongo::Client ] The client for this persistence
107
+ # context.
108
+ #
109
+ # @since 6.0.0
110
+ def client
111
+ @client ||= (client = Clients.with_name(client_name)
112
+ client = client.use(database_name) if database_name_option
113
+ client.with(client_options))
114
+ end
115
+
116
+ # Determine if this persistence context is equal to another.
117
+ #
118
+ # @example Compare two persistence contexts.
119
+ # context == other_context
120
+ #
121
+ # @param [ Object ] other The object to be compared with this one.
122
+ #
123
+ # @return [ true, false ] Whether the two persistence contexts are equal.
124
+ #
125
+ # @since 6.0.0
126
+ def ==(other)
127
+ return false unless other.is_a?(PersistenceContext)
128
+ options == other.options
129
+ end
130
+
131
+ private
132
+
133
+ def client_name
134
+ @client_name ||= options[:client] ||
135
+ Threaded.client_override ||
136
+ storage_options && __evaluate__(storage_options[:client])
137
+ end
138
+
139
+ def set_options!(opts)
140
+ @options ||= opts.each.reduce({}) do |_options, (key, value)|
141
+ unless VALID_OPTIONS.include?(key.to_sym)
142
+ raise Errors::InvalidPersistenceOption.new(key.to_sym, VALID_OPTIONS)
143
+ end
144
+ value ? _options.merge!(key => value) : _options
145
+ end
146
+ end
147
+
148
+ def __evaluate__(name)
149
+ return nil unless name
150
+ name.respond_to?(:call) ? name.call.to_sym : name.to_sym
151
+ end
152
+
153
+ def client_options
154
+ @client_options ||= options.select do |k, v|
155
+ Mongo::Client::VALID_OPTIONS.include?(k.to_sym)
156
+ end
157
+ end
158
+
159
+ def database_name_option
160
+ @database_name_option ||= options[:database] ||
161
+ Threaded.database_override ||
162
+ storage_options && storage_options[:database]
163
+ end
164
+
165
+ class << self
166
+
167
+ # Set the persistence context for a particular class or model instance.
168
+ #
169
+ # @example Set the persistence context for a class or model instance.
170
+ # PersistenceContext.set(model)
171
+ #
172
+ # @param [ Object ] object The class or model instance.
173
+ # @param [ Hash, Mongoid::PersistenceContext ] options_or_context The persistence
174
+ # options or a persistence context object.
175
+ #
176
+ # @return [ Mongoid::PersistenceContext ] The persistence context for the object.
177
+ #
178
+ # @since 6.0.0
179
+ def set(object, options_or_context)
180
+ context = PersistenceContext.new(object, options_or_context.is_a?(PersistenceContext) ?
181
+ options_or_context.options : options_or_context)
182
+ Thread.current["[mongoid][#{object.object_id}]:context"] = context
183
+ end
184
+
185
+ # Get the persistence context for a particular class or model instance.
186
+ #
187
+ # @example Get the persistence context for a class or model instance.
188
+ # PersistenceContext.get(model)
189
+ #
190
+ # @param [ Object ] object The class or model instance.
191
+ #
192
+ # @return [ Mongoid::PersistenceContext ] The persistence context for the object.
193
+ #
194
+ # @since 6.0.0
195
+ def get(object)
196
+ Thread.current["[mongoid][#{object.object_id}]:context"]
197
+ end
198
+
199
+ # Get the persistence context for a particular class or model instance.
200
+ #
201
+ # @example Get the persistence context for a class or model instance.
202
+ # PersistenceContext.get(model)
203
+ #
204
+ # @param [ Class, Object ] object The class or model instance.
205
+ # @param [ Mongo::Cluster ] cluster The original cluster before this context was used.
206
+ #
207
+ # @since 6.0.0
208
+ def clear(object, cluster = nil)
209
+ if context = get(object)
210
+ context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
211
+ end
212
+ Thread.current["[mongoid][#{object.object_id}]:context"] = nil
213
+ end
214
+ end
215
+ end
216
+ end
@@ -70,20 +70,6 @@ module Mongoid
70
70
  ensure
71
71
  QueryCache.enabled = enabled
72
72
  end
73
-
74
- # Execute the block with the query cache disabled.
75
- #
76
- # @example Execute without the cache.
77
- # QueryCache.uncached { collection.find }
78
- #
79
- # @return [ Object ] The result of the block.
80
- def uncached
81
- enabled = QueryCache.enabled?
82
- QueryCache.enabled = false
83
- yield
84
- ensure
85
- QueryCache.enabled = enabled
86
- end
87
73
  end
88
74
 
89
75
  # The middleware to be added to a rack application in order to activate the
@@ -183,7 +169,8 @@ module Mongoid
183
169
  end
184
170
  CODE
185
171
 
186
- alias_method_chain method_name, :clear_cache
172
+ alias_method "#{method_name}_without_clear_cache", method_name
173
+ alias_method method_name, "#{method_name}_with_clear_cache"
187
174
  end
188
175
  end
189
176
  end
@@ -221,7 +208,7 @@ module Mongoid
221
208
  super
222
209
  else
223
210
  unless cursor = cached_cursor
224
- server = read_or_server_selector.select_server(cluster)
211
+ server = read.select_server(cluster)
225
212
  cursor = CachedCursor.new(view, send_initial_query(server), server)
226
213
  QueryCache.cache_table[cache_key] = cursor
227
214
  end
@@ -234,13 +221,9 @@ module Mongoid
234
221
 
235
222
  private
236
223
 
237
- def read_or_server_selector
238
- respond_to?(:server_selector, true) ? server_selector : read
239
- end
240
-
241
224
  def cached_cursor
242
225
  if limit
243
- key = [ collection.namespace, selector, nil, skip, sort, projection, collation ]
226
+ key = [ collection.namespace, selector, nil, skip, sort, projection ]
244
227
  cursor = QueryCache.cache_table[key]
245
228
  if cursor
246
229
  limited_docs = cursor.to_a[0...limit.abs]
@@ -251,7 +234,7 @@ module Mongoid
251
234
  end
252
235
 
253
236
  def cache_key
254
- [ collection.namespace, selector, limit, skip, sort, projection, collation ]
237
+ [ collection.namespace, selector, limit, skip, sort, projection ]
255
238
  end
256
239
 
257
240
  def system_collection?
@@ -270,16 +253,8 @@ module Mongoid
270
253
  alias_query_cache_clear :insert_one, :insert_many
271
254
  end
272
255
  end
273
-
274
- # Bypass the query cache when reloading a document.
275
- module Document
276
- def reload
277
- QueryCache.uncached { super }
278
- end
279
- end
280
256
  end
281
257
  end
282
258
 
283
259
  Mongo::Collection.__send__(:include, Mongoid::QueryCache::Collection)
284
260
  Mongo::Collection::View.__send__(:include, Mongoid::QueryCache::View)
285
- Mongoid::Document.__send__(:include, Mongoid::QueryCache::Document)