mongoid 5.4.0 → 6.4.8

Sign up to get free protection for your applications and to get access to all the features.
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(