mongoid 5.4.0 → 6.4.8

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 (301) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +26 -0
  5. data/lib/config/locales/en.yml +40 -0
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic.rb +5 -5
  8. data/lib/mongoid/attributes/readonly.rb +22 -0
  9. data/lib/mongoid/attributes.rb +22 -21
  10. data/lib/mongoid/cacheable.rb +36 -0
  11. data/lib/mongoid/changeable.rb +36 -0
  12. data/lib/mongoid/clients/options.rb +55 -250
  13. data/lib/mongoid/clients/sessions.rb +113 -0
  14. data/lib/mongoid/clients/storage_options.rb +2 -69
  15. data/lib/mongoid/clients.rb +10 -63
  16. data/lib/mongoid/composable.rb +29 -2
  17. data/lib/mongoid/config.rb +1 -0
  18. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  19. data/lib/mongoid/contextual/atomic.rb +4 -4
  20. data/lib/mongoid/contextual/map_reduce.rb +7 -3
  21. data/lib/mongoid/contextual/memory.rb +9 -4
  22. data/lib/mongoid/contextual/mongo.rb +65 -30
  23. data/lib/mongoid/contextual/none.rb +12 -0
  24. data/lib/mongoid/copyable.rb +13 -6
  25. data/lib/mongoid/criteria/marshalable.rb +2 -2
  26. data/lib/mongoid/criteria/modifiable.rb +29 -3
  27. data/lib/mongoid/criteria/options.rb +25 -0
  28. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  29. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  30. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  32. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  33. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  34. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  35. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  36. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  37. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  38. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  39. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
  40. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  41. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  42. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  43. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  45. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  46. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  47. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  48. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  49. data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
  50. data/lib/mongoid/criteria/queryable/optional.rb +429 -0
  51. data/lib/mongoid/criteria/queryable/options.rb +153 -0
  52. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  53. data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
  54. data/lib/mongoid/criteria/queryable/selector.rb +212 -0
  55. data/lib/mongoid/criteria/queryable/smash.rb +104 -0
  56. data/lib/mongoid/criteria/queryable.rb +87 -0
  57. data/lib/mongoid/criteria.rb +6 -2
  58. data/lib/mongoid/document.rb +34 -41
  59. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  60. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
  61. data/lib/mongoid/errors/invalid_field.rb +2 -2
  62. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  63. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  64. data/lib/mongoid/errors/invalid_session_use.rb +24 -0
  65. data/lib/mongoid/errors.rb +3 -0
  66. data/lib/mongoid/evolvable.rb +1 -1
  67. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  68. data/lib/mongoid/extensions/date.rb +4 -1
  69. data/lib/mongoid/extensions/decimal128.rb +3 -3
  70. data/lib/mongoid/extensions/hash.rb +1 -0
  71. data/lib/mongoid/extensions/regexp.rb +1 -0
  72. data/lib/mongoid/extensions/string.rb +6 -3
  73. data/lib/mongoid/extensions/time.rb +4 -1
  74. data/lib/mongoid/extensions.rb +0 -4
  75. data/lib/mongoid/factory.rb +2 -1
  76. data/lib/mongoid/fields/validators/macro.rb +18 -0
  77. data/lib/mongoid/findable.rb +2 -2
  78. data/lib/mongoid/indexable.rb +16 -14
  79. data/lib/mongoid/interceptable.rb +9 -22
  80. data/lib/mongoid/matchable/all.rb +2 -2
  81. data/lib/mongoid/matchable/and.rb +3 -3
  82. data/lib/mongoid/matchable/default.rb +2 -2
  83. data/lib/mongoid/matchable/elem_match.rb +28 -0
  84. data/lib/mongoid/matchable/exists.rb +2 -2
  85. data/lib/mongoid/matchable/gt.rb +4 -2
  86. data/lib/mongoid/matchable/gte.rb +4 -2
  87. data/lib/mongoid/matchable/in.rb +2 -2
  88. data/lib/mongoid/matchable/lt.rb +4 -2
  89. data/lib/mongoid/matchable/lte.rb +4 -2
  90. data/lib/mongoid/matchable/ne.rb +2 -2
  91. data/lib/mongoid/matchable/nin.rb +2 -2
  92. data/lib/mongoid/matchable/nor.rb +37 -0
  93. data/lib/mongoid/matchable/or.rb +3 -3
  94. data/lib/mongoid/matchable/regexp.rb +3 -3
  95. data/lib/mongoid/matchable/size.rb +2 -2
  96. data/lib/mongoid/matchable.rb +16 -7
  97. data/lib/mongoid/persistable/creatable.rb +5 -3
  98. data/lib/mongoid/persistable/deletable.rb +5 -3
  99. data/lib/mongoid/persistable/destroyable.rb +1 -5
  100. data/lib/mongoid/persistable/settable.rb +5 -5
  101. data/lib/mongoid/persistable/updatable.rb +7 -14
  102. data/lib/mongoid/persistable/upsertable.rb +2 -1
  103. data/lib/mongoid/persistable.rb +4 -6
  104. data/lib/mongoid/persistence_context.rb +220 -0
  105. data/lib/mongoid/query_cache.rb +67 -23
  106. data/lib/mongoid/railtie.rb +17 -1
  107. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  108. data/lib/mongoid/relations/accessors.rb +3 -0
  109. data/lib/mongoid/relations/auto_save.rb +12 -4
  110. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  111. data/lib/mongoid/relations/counter_cache.rb +15 -5
  112. data/lib/mongoid/relations/eager/base.rb +3 -3
  113. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
  114. data/lib/mongoid/relations/eager/has_many.rb +1 -1
  115. data/lib/mongoid/relations/eager.rb +6 -11
  116. data/lib/mongoid/relations/embedded/batchable.rb +20 -18
  117. data/lib/mongoid/relations/embedded/in.rb +13 -1
  118. data/lib/mongoid/relations/embedded/many.rb +51 -10
  119. data/lib/mongoid/relations/embedded/one.rb +14 -1
  120. data/lib/mongoid/relations/macros.rb +9 -1
  121. data/lib/mongoid/relations/many.rb +4 -0
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/options.rb +2 -2
  124. data/lib/mongoid/relations/proxy.rb +1 -31
  125. data/lib/mongoid/relations/referenced/in.rb +19 -10
  126. data/lib/mongoid/relations/referenced/many.rb +30 -26
  127. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  128. data/lib/mongoid/relations/referenced/one.rb +15 -1
  129. data/lib/mongoid/relations/synchronization.rb +12 -12
  130. data/lib/mongoid/relations/targets/enumerable.rb +24 -4
  131. data/lib/mongoid/relations/touchable.rb +7 -4
  132. data/lib/mongoid/reloadable.rb +2 -2
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +1 -1
  135. data/lib/mongoid/stateful.rb +1 -0
  136. data/lib/mongoid/tasks/database.rb +3 -2
  137. data/lib/mongoid/threaded.rb +74 -0
  138. data/lib/mongoid/traversable.rb +1 -1
  139. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  140. data/lib/mongoid/version.rb +1 -1
  141. data/lib/mongoid.rb +6 -6
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
  143. data/spec/app/models/agent.rb +2 -0
  144. data/spec/app/models/album.rb +5 -1
  145. data/spec/app/models/array_field.rb +7 -0
  146. data/spec/app/models/artist.rb +21 -0
  147. data/spec/app/models/band.rb +3 -0
  148. data/spec/app/models/book.rb +2 -1
  149. data/spec/app/models/delegating_patient.rb +16 -0
  150. data/spec/app/models/dokument.rb +1 -0
  151. data/spec/app/models/ordered_post.rb +5 -0
  152. data/spec/app/models/oscar.rb +1 -2
  153. data/spec/app/models/page.rb +1 -1
  154. data/spec/app/models/person.rb +3 -3
  155. data/spec/app/models/princess.rb +2 -0
  156. data/spec/app/models/record.rb +1 -0
  157. data/spec/app/models/subscription.rb +1 -0
  158. data/spec/app/models/thing.rb +1 -1
  159. data/spec/config/mongoid.yml +15 -0
  160. data/spec/integration/document_spec.rb +22 -0
  161. data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
  162. data/spec/mongoid/atomic_spec.rb +5 -5
  163. data/spec/mongoid/attributes/nested_spec.rb +18 -14
  164. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  165. data/spec/mongoid/attributes_spec.rb +90 -5
  166. data/spec/mongoid/cacheable_spec.rb +112 -0
  167. data/spec/mongoid/changeable_spec.rb +58 -0
  168. data/spec/mongoid/clients/factory_spec.rb +80 -28
  169. data/spec/mongoid/clients/options_spec.rb +396 -95
  170. data/spec/mongoid/clients/sessions_spec.rb +334 -0
  171. data/spec/mongoid/clients_spec.rb +243 -101
  172. data/spec/mongoid/composable_spec.rb +7 -0
  173. data/spec/mongoid/config_spec.rb +67 -11
  174. data/spec/mongoid/contextual/atomic_spec.rb +3 -3
  175. data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
  176. data/spec/mongoid/contextual/mongo_spec.rb +275 -22
  177. data/spec/mongoid/contextual/none_spec.rb +15 -0
  178. data/spec/mongoid/copyable_spec.rb +13 -4
  179. data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
  180. data/spec/mongoid/criteria/options_spec.rb +29 -0
  181. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  182. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  183. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  184. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  185. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  186. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  187. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  189. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  190. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  191. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  192. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  193. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  194. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  195. data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
  196. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
  197. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  198. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  199. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  200. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  201. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  202. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  203. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  204. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  205. data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
  206. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  207. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  208. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  209. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
  210. data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
  211. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  212. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  213. data/spec/mongoid/criteria_spec.rb +156 -22
  214. data/spec/mongoid/document_spec.rb +100 -90
  215. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  216. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  217. data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
  218. data/spec/mongoid/extensions/boolean_spec.rb +14 -0
  219. data/spec/mongoid/extensions/date_spec.rb +2 -6
  220. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  221. data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
  222. data/spec/mongoid/extensions/float_spec.rb +8 -1
  223. data/spec/mongoid/extensions/hash_spec.rb +15 -0
  224. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  225. data/spec/mongoid/extensions/object_spec.rb +11 -0
  226. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  227. data/spec/mongoid/extensions/string_spec.rb +53 -4
  228. data/spec/mongoid/extensions/time_spec.rb +2 -6
  229. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  230. data/spec/mongoid/factory_spec.rb +11 -0
  231. data/spec/mongoid/fields_spec.rb +1 -1
  232. data/spec/mongoid/findable_spec.rb +47 -2
  233. data/spec/mongoid/indexable_spec.rb +15 -3
  234. data/spec/mongoid/interceptable_spec.rb +85 -19
  235. data/spec/mongoid/matchable/all_spec.rb +4 -4
  236. data/spec/mongoid/matchable/and_spec.rb +10 -10
  237. data/spec/mongoid/matchable/default_spec.rb +12 -12
  238. data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
  239. data/spec/mongoid/matchable/exists_spec.rb +5 -5
  240. data/spec/mongoid/matchable/gt_spec.rb +18 -7
  241. data/spec/mongoid/matchable/gte_spec.rb +17 -7
  242. data/spec/mongoid/matchable/in_spec.rb +5 -5
  243. data/spec/mongoid/matchable/lt_spec.rb +18 -7
  244. data/spec/mongoid/matchable/lte_spec.rb +18 -7
  245. data/spec/mongoid/matchable/ne_spec.rb +5 -5
  246. data/spec/mongoid/matchable/nin_spec.rb +5 -5
  247. data/spec/mongoid/matchable/nor_spec.rb +209 -0
  248. data/spec/mongoid/matchable/or_spec.rb +7 -7
  249. data/spec/mongoid/matchable/regexp_spec.rb +5 -5
  250. data/spec/mongoid/matchable/size_spec.rb +3 -3
  251. data/spec/mongoid/matchable_spec.rb +199 -54
  252. data/spec/mongoid/persistable/creatable_spec.rb +7 -2
  253. data/spec/mongoid/persistable/deletable_spec.rb +35 -1
  254. data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
  255. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  256. data/spec/mongoid/persistable/savable_spec.rb +34 -29
  257. data/spec/mongoid/persistable/settable_spec.rb +77 -27
  258. data/spec/mongoid/persistable/updatable_spec.rb +182 -3
  259. data/spec/mongoid/persistable_spec.rb +16 -16
  260. data/spec/mongoid/persistence_context_spec.rb +694 -0
  261. data/spec/mongoid/positional_spec.rb +1 -1
  262. data/spec/mongoid/query_cache_spec.rb +170 -12
  263. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  264. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  265. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
  266. data/spec/mongoid/relations/builders_spec.rb +37 -10
  267. data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
  268. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
  269. data/spec/mongoid/relations/eager_spec.rb +40 -0
  270. data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
  271. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  272. data/spec/mongoid/relations/macros_spec.rb +415 -7
  273. data/spec/mongoid/relations/metadata_spec.rb +15 -1
  274. data/spec/mongoid/relations/proxy_spec.rb +27 -1
  275. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  276. data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
  277. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
  278. data/spec/mongoid/relations/synchronization_spec.rb +48 -2
  279. data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
  280. data/spec/mongoid/relations/touchable_spec.rb +40 -0
  281. data/spec/mongoid/reloadable_spec.rb +51 -0
  282. data/spec/mongoid/scopable_spec.rb +13 -0
  283. data/spec/mongoid/serializable_spec.rb +0 -50
  284. data/spec/mongoid/threaded_spec.rb +68 -0
  285. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  286. data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
  287. data/spec/mongoid/validatable_spec.rb +16 -0
  288. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  289. data/spec/spec_helper.rb +101 -8
  290. data/spec/support/cluster_config.rb +158 -0
  291. data/spec/support/constraints.rb +101 -0
  292. data/spec/support/macros.rb +20 -0
  293. data/spec/support/session_registry.rb +50 -0
  294. data/spec/support/spec_config.rb +42 -0
  295. data.tar.gz.sig +0 -0
  296. metadata +163 -61
  297. metadata.gz.sig +0 -0
  298. data/lib/mongoid/clients/thread_options.rb +0 -19
  299. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  300. data/lib/mongoid/railties/document.rb +0 -12
  301. data/spec/mongoid/railties/document_spec.rb +0 -24
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
- require "mongoid/railties/document"
3
2
  require "rails"
4
3
  require "rails/mongoid"
5
4
 
@@ -103,6 +102,23 @@ module Rails
103
102
  puts "There is a configuration error with the current mongoid.yml."
104
103
  puts e.message
105
104
  end
105
+
106
+ # Include Controller extension that measures Mongoid runtime
107
+ # during request processing. The value then appears in Rails'
108
+ # instrumentation event `process_action.action_controller`.
109
+ #
110
+ # The measurement is made via internal Mongo monitoring subscription
111
+ initializer "mongoid.runtime-metric" do
112
+ require "mongoid/railties/controller_runtime"
113
+
114
+ ActiveSupport.on_load :action_controller do
115
+ include ::Mongoid::Railties::ControllerRuntime::ControllerExtension
116
+ end
117
+
118
+ Mongo::Monitoring::Global.subscribe Mongo::Monitoring::COMMAND,
119
+ ::Mongoid::Railties::ControllerRuntime::Collector.new
120
+ end
121
+
106
122
  end
107
123
  end
108
124
  end
@@ -0,0 +1,86 @@
1
+ module Mongoid
2
+ module Railties
3
+ module ControllerRuntime
4
+
5
+ # This extension mimics the Rails' internal method to
6
+ # measure ActiveRecord runtime during request processing.
7
+ # It appends MongoDB runtime value (`mongoid_runtime`) into payload
8
+ # of instrumentation event `process_action.action_controller`.
9
+ module ControllerExtension
10
+ extend ActiveSupport::Concern
11
+
12
+ protected
13
+
14
+ attr_internal :mongoid_runtime
15
+
16
+ # Reset the runtime before each action.
17
+ def process_action(action, *args)
18
+ Collector.reset_runtime
19
+ super
20
+ end
21
+
22
+ # Override to collect the measurements.
23
+ def cleanup_view_runtime
24
+ mongo_rt_before_render = Collector.reset_runtime
25
+ runtime = super
26
+ mongo_rt_after_render = Collector.reset_runtime
27
+ self.mongoid_runtime = mongo_rt_before_render + mongo_rt_after_render
28
+ runtime - mongo_rt_after_render
29
+ end
30
+
31
+ # Add the measurement to the instrumentation event payload.
32
+ def append_info_to_payload(payload)
33
+ super
34
+ payload[:mongoid_runtime] = (mongoid_runtime || 0) + Collector.reset_runtime
35
+ end
36
+
37
+ module ClassMethods
38
+
39
+ # Append MongoDB runtime information to ActionController runtime
40
+ # log message.
41
+ def log_process_action(payload)
42
+ messages = super
43
+ mongoid_runtime = payload[:mongoid_runtime]
44
+ messages << ("MongoDB: %.1fms" % mongoid_runtime.to_f) if mongoid_runtime
45
+ messages
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ # The Collector of MongoDB runtime metric, that subscribes to Mongo
53
+ # driver command monitoring. Stores the value within a thread-local
54
+ # variable to provide correct accounting when an application issues
55
+ # MongoDB operations from background threads.
56
+ class Collector
57
+
58
+ VARIABLE_NAME = "Mongoid.controller_runtime".freeze
59
+
60
+ def started _; end
61
+
62
+ def _completed e
63
+ Collector.runtime += e.duration
64
+ end
65
+ alias :succeeded :_completed
66
+ alias :failed :_completed
67
+
68
+ def self.runtime
69
+ Thread.current[VARIABLE_NAME] ||= 0
70
+ end
71
+
72
+ def self.runtime= value
73
+ Thread.current[VARIABLE_NAME] = value
74
+ end
75
+
76
+ def self.reset_runtime
77
+ to_now = runtime
78
+ self.runtime = 0
79
+ to_now
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -229,6 +229,9 @@ module Mongoid
229
229
  if value = get_relation(name, metadata, object)
230
230
  if value.respond_to?(:substitute)
231
231
  set_relation(name, value.substitute(object.substitutable))
232
+ else
233
+ value = __build__(name, value, metadata)
234
+ set_relation(name, value.substitute(object.substitutable))
232
235
  end
233
236
  else
234
237
  __build__(name, object.substitutable, metadata)
@@ -59,17 +59,25 @@ module Mongoid
59
59
  if metadata.autosave? && !metadata.embedded?
60
60
  save_method = :"autosave_documents_for_#{metadata.name}"
61
61
  define_method(save_method) do
62
-
63
62
  if before_callback_halted?
64
63
  self.before_callback_halted = false
65
64
  else
66
65
  __autosaving__ do
67
66
  if relation = ivar(metadata.name)
68
- options = persistence_options || {}
69
67
  if :belongs_to == metadata.macro
70
- relation.with(options).save if changed_for_autosave?(relation)
68
+ if changed_for_autosave?(relation)
69
+ relation.with(persistence_context) do |_relation|
70
+ _relation.save
71
+ end
72
+ end
71
73
  else
72
- Array(relation).each { |d| d.with(options).save if changed_for_autosave?(d) }
74
+ Array(relation).each do |doc|
75
+ if changed_for_autosave?(doc)
76
+ doc.with(persistence_context) do |d|
77
+ d.save
78
+ end
79
+ end
80
+ end
73
81
  end
74
82
  end
75
83
  end
@@ -26,8 +26,8 @@ module Mongoid
26
26
  end
27
27
  doc.reset_relation_criteria(metadata.inverse)
28
28
  end
29
- base.synced[metadata.foreign_key] = true
30
- doc.synced[metadata.inverse_foreign_key] = true
29
+ base._synced[metadata.foreign_key] = true
30
+ doc._synced[metadata.inverse_foreign_key] = true
31
31
  end
32
32
  end
33
33
 
@@ -45,8 +45,8 @@ module Mongoid
45
45
  inverse_keys.delete_one(inverse_record_id(doc))
46
46
  doc.reset_relation_criteria(metadata.inverse)
47
47
  end
48
- base.synced[metadata.foreign_key] = true
49
- doc.synced[metadata.inverse_foreign_key] = true
48
+ base._synced[metadata.foreign_key] = true
49
+ doc._synced[metadata.inverse_foreign_key] = true
50
50
  end
51
51
  end
52
52
 
@@ -15,7 +15,9 @@ module Mongoid
15
15
  #
16
16
  # @since 4.0.0
17
17
  def reset_counters(*counters)
18
- self.class.reset_counters(self, *counters)
18
+ self.class.with(persistence_context) do |_class|
19
+ _class.reset_counters(self, *counters)
20
+ end
19
21
  end
20
22
 
21
23
  module ClassMethods
@@ -111,12 +113,16 @@ module Mongoid
111
113
  original, current = attribute_change(foreign_key)
112
114
 
113
115
  unless original.nil?
114
- record.class.decrement_counter(cache_column, original)
116
+ record.class.with(persistence_context) do |_class|
117
+ _class.decrement_counter(cache_column, original)
118
+ end
115
119
  end
116
120
 
117
121
  unless current.nil?
118
122
  record[cache_column] = (record[cache_column] || 0) + 1
119
- record.class.increment_counter(cache_column, current) if record.persisted?
123
+ record.class.with(record.persistence_context) do |_class|
124
+ _class.increment_counter(cache_column, current) if record.persisted?
125
+ end
120
126
  end
121
127
  end
122
128
  end
@@ -127,7 +133,9 @@ module Mongoid
127
133
  record[cache_column] = (record[cache_column] || 0) + 1
128
134
 
129
135
  if record.persisted?
130
- record.class.increment_counter(cache_column, record._id)
136
+ record.class.with(record.persistence_context) do |_class|
137
+ _class.increment_counter(cache_column, record._id)
138
+ end
131
139
  record.remove_change(cache_column)
132
140
  end
133
141
  end
@@ -138,7 +146,9 @@ module Mongoid
138
146
  record[cache_column] = (record[cache_column] || 0) - 1 unless record.frozen?
139
147
 
140
148
  if record.persisted?
141
- record.class.decrement_counter(cache_column, record._id)
149
+ record.class.with(record.persistence_context) do |_class|
150
+ _class.decrement_counter(cache_column, record._id)
151
+ end
142
152
  record.remove_change(cache_column)
143
153
  end
144
154
  end
@@ -48,7 +48,7 @@ module Mongoid
48
48
  @loaded = []
49
49
  while shift_metadata
50
50
  preload
51
- @loaded << @docs.collect { |d| d.send(@metadata.name) }
51
+ @loaded << @docs.collect { |d| d.send(@metadata.name) if d.respond_to?(@metadata.name) }
52
52
  end
53
53
  @loaded.flatten
54
54
  end
@@ -99,12 +99,12 @@ module Mongoid
99
99
  # @example Return a hash with the current documents grouped by key.
100
100
  # loader.grouped_docs
101
101
  #
102
- # @return [ Hash ] hash with groupd documents.
102
+ # @return [ Hash ] hash with grouped documents.
103
103
  #
104
104
  # @since 4.0.0
105
105
  def grouped_docs
106
106
  @grouped_docs[@metadata.name] ||= @docs.group_by do |doc|
107
- doc.send(group_by_key)
107
+ doc.send(group_by_key) if doc.respond_to?(group_by_key)
108
108
  end
109
109
  end
110
110
 
@@ -17,7 +17,7 @@ module Mongoid
17
17
 
18
18
  @docs.each do |d|
19
19
  keys = d.send(group_by_key)
20
- docs = entries.values_at(*keys)
20
+ docs = entries.values_at(*keys).compact
21
21
  set_relation(d, docs)
22
22
  end
23
23
  end
@@ -31,7 +31,7 @@ module Mongoid
31
31
  end
32
32
 
33
33
  def set_relation(doc, element)
34
- doc.__build__(@metadata.name, element, @metadata)
34
+ doc.__build__(@metadata.name, element, @metadata) unless doc.blank?
35
35
  end
36
36
 
37
37
  def group_by_key
@@ -22,7 +22,7 @@ module Mongoid
22
22
  end
23
23
 
24
24
  def set_relation(doc, element)
25
- doc.__build__(@metadata.name, element, @metadata)
25
+ doc.__build__(@metadata.name, element, @metadata) unless doc.blank?
26
26
  end
27
27
 
28
28
  def group_by_key
@@ -22,19 +22,14 @@ module Mongoid
22
22
  end
23
23
 
24
24
  def preload(relations, docs)
25
- grouped_relations = relations.group_by do |metadata|
26
- metadata.inverse_class_name
27
- end
28
- grouped_relations.keys.each do |_klass|
29
- grouped_relations[_klass] = grouped_relations[_klass].group_by do |metadata|
30
- metadata.relation
25
+ relations.group_by(&:inverse_class_name)
26
+ .values
27
+ .each do |associations|
28
+ associations.group_by(&:relation)
29
+ .each do |relation, association|
30
+ relation.eager_load_klass.new(association, docs).run
31
31
  end
32
32
  end
33
- grouped_relations.each do |_klass, associations|
34
- docs = associations.collect do |_relation, association|
35
- _relation.eager_load_klass.new(association, docs).run
36
- end.flatten
37
- end
38
33
  end
39
34
  end
40
35
  end
@@ -8,19 +8,19 @@ module Mongoid
8
8
  module Batchable
9
9
  include Positional
10
10
 
11
- # Insert new documents as a batch push ($pushAll). This ensures that
11
+ # Insert new documents as a batch push ($push with $each). This ensures that
12
12
  # all callbacks are run at the appropriate time and only 1 request is
13
13
  # made to the database.
14
14
  #
15
15
  # @example Execute the batch push.
16
- # batchable.batch_push([ doc_one, doc_two ])
16
+ # batchable.batch_insert([ doc_one, doc_two ])
17
17
  #
18
18
  # @param [ Array<Document> ] docs The docs to add.
19
19
  #
20
20
  # @return [ Array<Hash> ] The inserts.
21
21
  #
22
- # @since 5.4.0
23
- def batch_push(docs)
22
+ # @since 3.0.0
23
+ def batch_insert(docs)
24
24
  execute_batch_push(docs)
25
25
  end
26
26
 
@@ -38,7 +38,8 @@ module Mongoid
38
38
  pre_process_batch_remove(docs, :delete)
39
39
  unless docs.empty?
40
40
  collection.find(selector).update_one(
41
- positionally(selector, "$unset" => { path => true })
41
+ positionally(selector, "$unset" => { path => true }),
42
+ session: _session
42
43
  )
43
44
  post_process_batch_remove(docs, :delete)
44
45
  end
@@ -58,7 +59,8 @@ module Mongoid
58
59
  removals = pre_process_batch_remove(docs, method)
59
60
  if !docs.empty?
60
61
  collection.find(selector).update_one(
61
- positionally(selector, "$pullAll" => { path => removals })
62
+ positionally(selector, "$pullAll" => { path => removals }),
63
+ session: _session
62
64
  )
63
65
  post_process_batch_remove(docs, method)
64
66
  end
@@ -85,7 +87,7 @@ module Mongoid
85
87
  else
86
88
  batch_remove(target.dup)
87
89
  end
88
- else
90
+ elsif target != docs
89
91
  base.delayed_atomic_sets.clear unless _assigning?
90
92
  docs = normalize_docs(docs).compact
91
93
  target.clear and _unscoped.clear
@@ -116,26 +118,25 @@ module Mongoid
116
118
  end
117
119
  end
118
120
 
119
- # Perform a batch persist of the provided documents with the supplied
120
- # operation.
121
+ # Perform a batch persist of the provided documents with a $set.
121
122
  #
122
123
  # @api private
123
124
  #
124
- # @example Perform a batch operation.
125
+ #@example Perform a batch $set.
125
126
  # batchable.execute_batch_set(docs)
126
127
  #
127
128
  # @param [ Array<Document> ] docs The docs to persist.
128
- # @param [ String ] operation The atomic operation.
129
129
  #
130
130
  # @return [ Array<Hash> ] The inserts.
131
131
  #
132
- # @since 5.4.0
132
+ # @since 7.0.0
133
133
  def execute_batch_set(docs)
134
134
  self.inserts_valid = true
135
135
  inserts = pre_process_batch_insert(docs)
136
136
  if insertable?
137
137
  collection.find(selector).update_one(
138
- positionally(selector, '$set' => { path => inserts })
138
+ positionally(selector, '$set' => { path => inserts }),
139
+ session: _session
139
140
  )
140
141
  post_process_batch_insert(docs)
141
142
  end
@@ -150,17 +151,18 @@ module Mongoid
150
151
  # batchable.execute_batch_push(docs)
151
152
  #
152
153
  # @param [ Array<Document> ] docs The docs to persist.
153
- # @param [ String ] operation The atomic operation.
154
154
  #
155
155
  # @return [ Array<Hash> ] The inserts.
156
156
  #
157
- # @since 5.4.0
157
+ # @since 7.0.0
158
158
  def execute_batch_push(docs)
159
159
  self.inserts_valid = true
160
160
  pushes = pre_process_batch_insert(docs)
161
161
  if insertable?
162
162
  collection.find(selector).update_one(
163
- positionally(selector, '$push' => { path => { '$each' => pushes } }))
163
+ positionally(selector, '$push' => { path => { '$each' => pushes } }),
164
+ session: _session
165
+ )
164
166
  post_process_batch_insert(docs)
165
167
  end
166
168
  pushes
@@ -303,7 +305,7 @@ module Mongoid
303
305
  self.inserts_valid = false
304
306
  end
305
307
  end
306
- doc.as_document
308
+ doc.send(:as_attributes)
307
309
  end
308
310
  end
309
311
 
@@ -332,7 +334,7 @@ module Mongoid
332
334
  _unscoped.delete_one(doc)
333
335
  unbind_one(doc)
334
336
  execute_callback :after_remove, doc
335
- doc.as_document
337
+ doc.send(:as_attributes)
336
338
  end
337
339
  end
338
340
 
@@ -8,6 +8,18 @@ module Mongoid
8
8
  # multiple documents.
9
9
  class In < Relations::One
10
10
 
11
+ # The allowed options when defining this relation.
12
+ #
13
+ # @return [ Array<Symbol> ] The allowed options when defining this relation.
14
+ #
15
+ # @since 6.0.0
16
+ VALID_OPTIONS = [
17
+ :autobuild,
18
+ :cyclic,
19
+ :polymorphic,
20
+ :touch
21
+ ].freeze
22
+
11
23
  # Instantiate a new embedded_in relation.
12
24
  #
13
25
  # @example Create the new relation.
@@ -207,7 +219,7 @@ module Mongoid
207
219
  #
208
220
  # @since 2.1.0
209
221
  def valid_options
210
- [ :autobuild, :cyclic, :polymorphic, :touch ]
222
+ VALID_OPTIONS
211
223
  end
212
224
 
213
225
  # Get the default validation setting for the relation. Determines if
@@ -10,6 +10,23 @@ module Mongoid
10
10
  class Many < Relations::Many
11
11
  include Batchable
12
12
 
13
+ # The allowed options when defining this relation.
14
+ #
15
+ # @return [ Array<Symbol> ] The allowed options when defining this relation.
16
+ #
17
+ # @since 6.0.0
18
+ VALID_OPTIONS = [
19
+ :as,
20
+ :cascade_callbacks,
21
+ :cyclic,
22
+ :order,
23
+ :store_as,
24
+ :before_add,
25
+ :after_add,
26
+ :before_remove,
27
+ :after_remove
28
+ ].freeze
29
+
13
30
  # Appends a document or array of documents to the relation. Will set
14
31
  # the parent and update the index in the process.
15
32
  #
@@ -41,11 +58,7 @@ module Mongoid
41
58
  #
42
59
  # @since 2.0.0.rc.1
43
60
  def as_document
44
- attributes = []
45
- _unscoped.each do |doc|
46
- attributes.push(doc.as_document)
47
- end
48
- attributes
61
+ as_attributes.collect { |attrs| BSON::Document.new(attrs) }
49
62
  end
50
63
 
51
64
  # Appends an array of documents to the relation. Performs a batch
@@ -60,7 +73,7 @@ module Mongoid
60
73
  #
61
74
  # @since 2.4.0
62
75
  def concat(docs)
63
- batch_push(docs) unless docs.empty?
76
+ batch_insert(docs) unless docs.empty?
64
77
  self
65
78
  end
66
79
 
@@ -281,6 +294,29 @@ module Mongoid
281
294
  end
282
295
  end
283
296
 
297
+ # Shift documents off the relation. This can be a single document or
298
+ # multiples, and will automatically persist the changes.
299
+ #
300
+ # @example Shift a single document.
301
+ # relation.shift
302
+ #
303
+ # @example Shift multiple documents.
304
+ # relation.shift(3)
305
+ #
306
+ # @param [ Integer ] count The number of documents to shift, or 1 if not
307
+ # provided.
308
+ #
309
+ # @return [ Document, Array<Document> ] The shifted document(s).
310
+ def shift(count = nil)
311
+ if count
312
+ if target.size > 0 && docs = target[0, count]
313
+ docs.each { |doc| delete(doc) }
314
+ end
315
+ else
316
+ delete(target[0])
317
+ end
318
+ end
319
+
284
320
  # Substitutes the supplied target documents for the existing documents
285
321
  # in the relation.
286
322
  #
@@ -496,6 +532,14 @@ module Mongoid
496
532
  @_unscoped = docs
497
533
  end
498
534
 
535
+ def as_attributes
536
+ attributes = []
537
+ _unscoped.each do |doc|
538
+ attributes.push(doc.as_document)
539
+ end
540
+ attributes
541
+ end
542
+
499
543
  class << self
500
544
 
501
545
  # Return the builder that is responsible for generating the documents
@@ -617,10 +661,7 @@ module Mongoid
617
661
  #
618
662
  # @since 2.1.0
619
663
  def valid_options
620
- [
621
- :as, :cascade_callbacks, :cyclic, :order, :store_as,
622
- :before_add, :after_add, :before_remove, :after_remove
623
- ]
664
+ VALID_OPTIONS
624
665
  end
625
666
 
626
667
  # Get the default validation setting for the relation. Determines if
@@ -7,6 +7,19 @@ module Mongoid
7
7
  # relations.
8
8
  class One < Relations::One
9
9
 
10
+ # The allowed options when defining this relation.
11
+ #
12
+ # @return [ Array<Symbol> ] The allowed options when defining this relation.
13
+ #
14
+ # @since 6.0.0
15
+ VALID_OPTIONS = [
16
+ :autobuild,
17
+ :as,
18
+ :cascade_callbacks,
19
+ :cyclic,
20
+ :store_as
21
+ ].freeze
22
+
10
23
  # Instantiate a new embeds_one relation.
11
24
  #
12
25
  # @example Create the new proxy.
@@ -200,7 +213,7 @@ module Mongoid
200
213
  #
201
214
  # @since 2.1.0
202
215
  def valid_options
203
- [ :autobuild, :as, :cascade_callbacks, :cyclic, :store_as ]
216
+ VALID_OPTIONS
204
217
  end
205
218
 
206
219
  # Get the default validation setting for the relation. Determines if
@@ -140,6 +140,7 @@ module Mongoid
140
140
  aliased_fields[name.to_s] = meta.foreign_key
141
141
  touchable(meta)
142
142
  add_counter_cache_callbacks(meta) if meta.counter_cached?
143
+ validates(name, presence: true) if require_association?(options)
143
144
  meta
144
145
  end
145
146
 
@@ -197,7 +198,7 @@ module Mongoid
197
198
  reference(meta, Array)
198
199
  autosave(meta)
199
200
  validates_relation(meta)
200
- synced(meta)
201
+ _synced(meta)
201
202
  meta
202
203
  end
203
204
 
@@ -350,9 +351,16 @@ module Mongoid
350
351
  # @param [ Symbol ] name The name of the relation.
351
352
  # @param [ Metadata ] metadata The metadata for the relation.
352
353
  def relate(name, metadata)
354
+ Fields::Validators::Macro.validate_relation(self, name)
353
355
  self.relations = relations.merge(name.to_s => metadata)
354
356
  getter(name, metadata).setter(name, metadata).existence_check(name)
355
357
  end
358
+
359
+ def require_association?(options = {})
360
+ required = options[:required] if options.key?(:required)
361
+ required = !options[:optional] if options.key?(:optional) && required.nil?
362
+ required.nil? ? Mongoid.belongs_to_required_by_default : required
363
+ end
356
364
  end
357
365
  end
358
366
  end
@@ -213,6 +213,10 @@ module Mongoid
213
213
 
214
214
  private
215
215
 
216
+ def _session
217
+ base.send(:_session)
218
+ end
219
+
216
220
  # Find the first object given the supplied attributes or create/initialize it.
217
221
  #
218
222
  # @example Find or create|initialize.
@@ -778,10 +778,10 @@ module Mongoid
778
778
  #
779
779
  # @since 2.0.0.rc.1
780
780
  def validate?
781
- unless self[:validate].nil?
782
- self[:validate]
783
- else
781
+ if self[:validate].nil?
784
782
  self[:validate] = relation.validation_default
783
+ else
784
+ self[:validate]
785
785
  end
786
786
  end
787
787
 
@@ -17,7 +17,7 @@ module Mongoid
17
17
  :name,
18
18
  :relation,
19
19
  :validate
20
- ]
20
+ ].freeze
21
21
 
22
22
  # Determine if the provided options are valid for the relation.
23
23
  #
@@ -32,7 +32,7 @@ module Mongoid
32
32
  #
33
33
  # @since 2.1.0
34
34
  def validate!(options)
35
- valid_options = options[:relation].valid_options.concat(COMMON)
35
+ valid_options = options[:relation]::VALID_OPTIONS + COMMON
36
36
  options.keys.each do |key|
37
37
  if !valid_options.include?(key)
38
38
  raise Errors::InvalidOptions.new(