mongoid 2.4.9 → 3.0.0.rc

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 (351) hide show
  1. data/CHANGELOG.md +869 -8
  2. data/LICENSE +1 -1
  3. data/README.md +10 -11
  4. data/Rakefile +2 -17
  5. data/lib/config/locales/en.yml +441 -51
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic/paths/embedded/many.rb +6 -6
  8. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -5
  9. data/lib/mongoid/atomic/paths/embedded.rb +4 -5
  10. data/lib/mongoid/atomic/paths/root.rb +4 -5
  11. data/lib/mongoid/atomic.rb +16 -6
  12. data/lib/mongoid/attributes/processing.rb +14 -10
  13. data/lib/mongoid/attributes/readonly.rb +56 -0
  14. data/lib/mongoid/attributes.rb +95 -32
  15. data/lib/mongoid/callbacks.rb +100 -42
  16. data/lib/mongoid/collections/retry.rb +2 -3
  17. data/lib/mongoid/components.rb +10 -22
  18. data/lib/mongoid/config/environment.rb +4 -3
  19. data/lib/mongoid/config/inflections.rb +6 -0
  20. data/lib/mongoid/config/options.rb +1 -1
  21. data/lib/mongoid/config/validators/option.rb +25 -0
  22. data/lib/mongoid/config/validators/session.rb +140 -0
  23. data/lib/mongoid/config/validators.rb +3 -0
  24. data/lib/mongoid/config.rb +87 -233
  25. data/lib/mongoid/contextual/aggregable/memory.rb +98 -0
  26. data/lib/mongoid/contextual/aggregable/mongo.rb +181 -0
  27. data/lib/mongoid/contextual/atomic.rb +179 -0
  28. data/lib/mongoid/contextual/command.rb +43 -0
  29. data/lib/mongoid/contextual/find_and_modify.rb +66 -0
  30. data/lib/mongoid/contextual/map_reduce.rb +273 -0
  31. data/lib/mongoid/contextual/memory.rb +383 -0
  32. data/lib/mongoid/contextual/mongo.rb +543 -0
  33. data/lib/mongoid/contextual.rb +50 -0
  34. data/lib/mongoid/copyable.rb +2 -2
  35. data/lib/mongoid/criteria.rb +436 -248
  36. data/lib/mongoid/criterion/inspection.rb +14 -8
  37. data/lib/mongoid/criterion/scoping.rb +114 -44
  38. data/lib/mongoid/dirty.rb +152 -67
  39. data/lib/mongoid/document.rb +68 -49
  40. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  41. data/lib/mongoid/errors/callback.rb +5 -6
  42. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  43. data/lib/mongoid/errors/document_not_found.rb +98 -17
  44. data/lib/mongoid/errors/eager_load.rb +3 -6
  45. data/lib/mongoid/errors/invalid_collection.rb +3 -3
  46. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  47. data/lib/mongoid/errors/invalid_database.rb +3 -3
  48. data/lib/mongoid/errors/invalid_field.rb +54 -8
  49. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  50. data/lib/mongoid/errors/invalid_find.rb +3 -3
  51. data/lib/mongoid/errors/invalid_index.rb +28 -0
  52. data/lib/mongoid/errors/invalid_options.rb +4 -4
  53. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  54. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  55. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  56. data/lib/mongoid/errors/invalid_time.rb +3 -6
  57. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  58. data/lib/mongoid/errors/mixed_relations.rb +4 -9
  59. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  60. data/lib/mongoid/errors/mongoid_error.rb +54 -3
  61. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  62. data/lib/mongoid/errors/no_default_session.rb +23 -0
  63. data/lib/mongoid/errors/no_environment.rb +3 -3
  64. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  65. data/lib/mongoid/errors/no_parent.rb +24 -0
  66. data/lib/mongoid/errors/no_session_config.rb +22 -0
  67. data/lib/mongoid/errors/no_session_database.rb +27 -0
  68. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  69. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  70. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  71. data/lib/mongoid/errors/scope_overwrite.rb +4 -4
  72. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +4 -4
  73. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  74. data/lib/mongoid/errors/unsaved_document.rb +4 -8
  75. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  76. data/lib/mongoid/errors/unsupported_version.rb +4 -4
  77. data/lib/mongoid/errors/validations.rb +7 -6
  78. data/lib/mongoid/errors/versioning_not_on_root.rb +23 -0
  79. data/lib/mongoid/errors.rb +22 -1
  80. data/lib/mongoid/extensions/array.rb +127 -0
  81. data/lib/mongoid/extensions/big_decimal.rb +42 -0
  82. data/lib/mongoid/extensions/boolean.rb +24 -0
  83. data/lib/mongoid/extensions/date.rb +70 -0
  84. data/lib/mongoid/extensions/date_time.rb +68 -0
  85. data/lib/mongoid/extensions/false_class.rb +26 -0
  86. data/lib/mongoid/extensions/float.rb +44 -0
  87. data/lib/mongoid/extensions/hash.rb +91 -0
  88. data/lib/mongoid/extensions/integer.rb +54 -0
  89. data/lib/mongoid/extensions/module.rb +28 -0
  90. data/lib/mongoid/extensions/nil_class.rb +21 -0
  91. data/lib/mongoid/extensions/object.rb +188 -0
  92. data/lib/mongoid/extensions/object_id.rb +53 -0
  93. data/lib/mongoid/extensions/range.rb +55 -0
  94. data/lib/mongoid/extensions/regexp.rb +27 -0
  95. data/lib/mongoid/extensions/set.rb +55 -0
  96. data/lib/mongoid/extensions/string.rb +155 -0
  97. data/lib/mongoid/extensions/symbol.rb +54 -0
  98. data/lib/mongoid/extensions/time.rb +78 -0
  99. data/lib/mongoid/extensions/time_with_zone.rb +55 -0
  100. data/lib/mongoid/extensions/true_class.rb +26 -0
  101. data/lib/mongoid/extensions.rb +28 -76
  102. data/lib/mongoid/factory.rb +4 -4
  103. data/lib/mongoid/fields/foreign_key.rb +134 -0
  104. data/lib/mongoid/fields/localized.rb +73 -0
  105. data/lib/mongoid/fields/standard.rb +268 -0
  106. data/lib/mongoid/fields/validators/macro.rb +83 -0
  107. data/lib/mongoid/fields/validators.rb +2 -0
  108. data/lib/mongoid/fields.rb +129 -194
  109. data/lib/mongoid/finders.rb +42 -43
  110. data/lib/mongoid/hierarchy.rb +25 -14
  111. data/lib/mongoid/identity_map.rb +39 -12
  112. data/lib/mongoid/indexes/validators/options.rb +80 -0
  113. data/lib/mongoid/indexes.rb +66 -15
  114. data/lib/mongoid/inspection.rb +1 -1
  115. data/lib/mongoid/javascript.rb +1 -1
  116. data/lib/mongoid/json.rb +2 -2
  117. data/lib/mongoid/loggable.rb +69 -0
  118. data/lib/mongoid/matchers/all.rb +7 -8
  119. data/lib/mongoid/matchers/and.rb +3 -3
  120. data/lib/mongoid/matchers/default.rb +6 -4
  121. data/lib/mongoid/matchers/exists.rb +2 -2
  122. data/lib/mongoid/matchers/gt.rb +2 -2
  123. data/lib/mongoid/matchers/gte.rb +2 -2
  124. data/lib/mongoid/matchers/in.rb +3 -7
  125. data/lib/mongoid/matchers/lt.rb +2 -2
  126. data/lib/mongoid/matchers/lte.rb +2 -2
  127. data/lib/mongoid/matchers/ne.rb +2 -2
  128. data/lib/mongoid/matchers/nin.rb +2 -2
  129. data/lib/mongoid/matchers/or.rb +2 -2
  130. data/lib/mongoid/matchers/size.rb +2 -2
  131. data/lib/mongoid/matchers/strategies.rb +3 -3
  132. data/lib/mongoid/matchers.rb +1 -1
  133. data/lib/mongoid/multi_parameter_attributes.rb +8 -10
  134. data/lib/mongoid/nested_attributes.rb +17 -9
  135. data/lib/mongoid/observer.rb +1 -2
  136. data/lib/mongoid/paranoia.rb +13 -18
  137. data/lib/mongoid/persistence/atomic/add_to_set.rb +5 -9
  138. data/lib/mongoid/persistence/atomic/bit.rb +5 -7
  139. data/lib/mongoid/persistence/atomic/inc.rb +5 -7
  140. data/lib/mongoid/persistence/atomic/operation.rb +45 -6
  141. data/lib/mongoid/persistence/atomic/pop.rb +5 -7
  142. data/lib/mongoid/persistence/atomic/pull.rb +5 -7
  143. data/lib/mongoid/persistence/atomic/pull_all.rb +5 -7
  144. data/lib/mongoid/persistence/atomic/push.rb +4 -10
  145. data/lib/mongoid/persistence/atomic/push_all.rb +4 -10
  146. data/lib/mongoid/persistence/atomic/rename.rb +6 -7
  147. data/lib/mongoid/persistence/atomic/sets.rb +5 -7
  148. data/lib/mongoid/persistence/atomic/unset.rb +4 -5
  149. data/lib/mongoid/persistence/atomic.rb +2 -2
  150. data/lib/mongoid/persistence/deletion.rb +2 -2
  151. data/lib/mongoid/persistence/insertion.rb +10 -16
  152. data/lib/mongoid/persistence/modification.rb +5 -9
  153. data/lib/mongoid/persistence/operations/embedded/insert.rb +7 -6
  154. data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -5
  155. data/lib/mongoid/persistence/operations/insert.rb +4 -4
  156. data/lib/mongoid/persistence/operations/remove.rb +4 -4
  157. data/lib/mongoid/persistence/operations/update.rb +5 -5
  158. data/lib/mongoid/persistence/operations.rb +6 -19
  159. data/lib/mongoid/persistence.rb +64 -27
  160. data/lib/mongoid/railtie.rb +26 -11
  161. data/lib/mongoid/railties/database.rake +22 -108
  162. data/lib/mongoid/relations/accessors.rb +119 -19
  163. data/lib/mongoid/relations/auto_save.rb +59 -5
  164. data/lib/mongoid/relations/binding.rb +211 -2
  165. data/lib/mongoid/relations/bindings/embedded/in.rb +16 -22
  166. data/lib/mongoid/relations/bindings/embedded/many.rb +9 -50
  167. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -16
  168. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -57
  169. data/lib/mongoid/relations/bindings/referenced/many.rb +8 -20
  170. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -19
  171. data/lib/mongoid/relations/bindings/referenced/one.rb +10 -24
  172. data/lib/mongoid/relations/builder.rb +3 -3
  173. data/lib/mongoid/relations/builders/embedded/in.rb +5 -5
  174. data/lib/mongoid/relations/builders/embedded/many.rb +12 -12
  175. data/lib/mongoid/relations/builders/embedded/one.rb +6 -6
  176. data/lib/mongoid/relations/builders/nested_attributes/many.rb +8 -8
  177. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -4
  178. data/lib/mongoid/relations/builders/referenced/in.rb +4 -4
  179. data/lib/mongoid/relations/builders/referenced/many.rb +5 -5
  180. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +7 -5
  181. data/lib/mongoid/relations/builders/referenced/one.rb +5 -5
  182. data/lib/mongoid/relations/builders.rb +19 -16
  183. data/lib/mongoid/relations/cascading/delete.rb +12 -4
  184. data/lib/mongoid/relations/cascading/destroy.rb +3 -3
  185. data/lib/mongoid/relations/cascading/nullify.rb +3 -3
  186. data/lib/mongoid/relations/cascading/restrict.rb +37 -0
  187. data/lib/mongoid/relations/cascading.rb +6 -4
  188. data/lib/mongoid/relations/constraint.rb +4 -3
  189. data/lib/mongoid/relations/conversions.rb +5 -6
  190. data/lib/mongoid/relations/cyclic.rb +7 -7
  191. data/lib/mongoid/relations/embedded/batchable.rb +346 -0
  192. data/lib/mongoid/relations/embedded/in.rb +23 -12
  193. data/lib/mongoid/relations/embedded/many.rb +99 -148
  194. data/lib/mongoid/relations/embedded/one.rb +25 -14
  195. data/lib/mongoid/relations/macros.rb +105 -60
  196. data/lib/mongoid/relations/many.rb +93 -14
  197. data/lib/mongoid/relations/metadata.rb +231 -45
  198. data/lib/mongoid/relations/nested_builder.rb +3 -5
  199. data/lib/mongoid/relations/one.rb +14 -2
  200. data/lib/mongoid/relations/options.rb +2 -2
  201. data/lib/mongoid/relations/polymorphic.rb +9 -9
  202. data/lib/mongoid/relations/proxy.rb +60 -31
  203. data/lib/mongoid/relations/referenced/in.rb +40 -15
  204. data/lib/mongoid/relations/referenced/many.rb +116 -122
  205. data/lib/mongoid/relations/referenced/many_to_many.rb +101 -46
  206. data/lib/mongoid/relations/referenced/one.rb +34 -13
  207. data/lib/mongoid/relations/reflections.rb +3 -3
  208. data/lib/mongoid/relations/synchronization.rb +19 -23
  209. data/lib/mongoid/relations/targets/enumerable.rb +86 -57
  210. data/lib/mongoid/relations/touchable.rb +32 -0
  211. data/lib/mongoid/relations.rb +6 -6
  212. data/lib/mongoid/reloading.rb +12 -14
  213. data/lib/mongoid/scoping.rb +329 -0
  214. data/lib/mongoid/serialization.rb +13 -30
  215. data/lib/mongoid/sessions/factory.rb +106 -0
  216. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  217. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  218. data/lib/mongoid/sessions/validators.rb +2 -0
  219. data/lib/mongoid/sessions.rb +359 -0
  220. data/lib/mongoid/sharding.rb +6 -6
  221. data/lib/mongoid/state.rb +6 -7
  222. data/lib/mongoid/threaded/lifecycle.rb +21 -21
  223. data/lib/mongoid/threaded/sessions.rb +0 -0
  224. data/lib/mongoid/threaded.rb +167 -59
  225. data/lib/mongoid/timestamps/created.rb +8 -4
  226. data/lib/mongoid/timestamps/timeless.rb +6 -4
  227. data/lib/mongoid/timestamps/updated.rb +3 -3
  228. data/lib/mongoid/timestamps.rb +1 -1
  229. data/lib/mongoid/unit_of_work.rb +61 -0
  230. data/lib/mongoid/validations/associated.rb +2 -2
  231. data/lib/mongoid/validations/format.rb +2 -2
  232. data/lib/mongoid/validations/presence.rb +34 -4
  233. data/lib/mongoid/validations/uniqueness.rb +103 -25
  234. data/lib/mongoid/validations.rb +62 -20
  235. data/lib/mongoid/version.rb +2 -2
  236. data/lib/mongoid/versioning.rb +25 -26
  237. data/lib/mongoid.rb +24 -39
  238. data/lib/rack/mongoid/middleware/identity_map.rb +3 -3
  239. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -1
  240. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +59 -19
  241. data/lib/rails/generators/mongoid/model/model_generator.rb +7 -7
  242. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +2 -2
  243. data/lib/rails/generators/mongoid/observer/observer_generator.rb +4 -4
  244. data/lib/rails/generators/mongoid_generator.rb +5 -5
  245. data/lib/rails/mongoid.rb +69 -25
  246. metadata +93 -155
  247. data/lib/config/locales/bg.yml +0 -61
  248. data/lib/config/locales/de.yml +0 -61
  249. data/lib/config/locales/en-GB.yml +0 -64
  250. data/lib/config/locales/es.yml +0 -59
  251. data/lib/config/locales/fr.yml +0 -62
  252. data/lib/config/locales/hi.yml +0 -53
  253. data/lib/config/locales/hu.yml +0 -64
  254. data/lib/config/locales/id.yml +0 -62
  255. data/lib/config/locales/it.yml +0 -59
  256. data/lib/config/locales/ja.yml +0 -57
  257. data/lib/config/locales/kr.yml +0 -54
  258. data/lib/config/locales/nl.yml +0 -61
  259. data/lib/config/locales/pl.yml +0 -59
  260. data/lib/config/locales/pt-BR.yml +0 -60
  261. data/lib/config/locales/pt.yml +0 -60
  262. data/lib/config/locales/ro.yml +0 -66
  263. data/lib/config/locales/ru.yml +0 -61
  264. data/lib/config/locales/sv.yml +0 -60
  265. data/lib/config/locales/vi.yml +0 -62
  266. data/lib/config/locales/zh-CN.yml +0 -53
  267. data/lib/mongoid/collection.rb +0 -157
  268. data/lib/mongoid/collections/master.rb +0 -45
  269. data/lib/mongoid/collections/operations.rb +0 -44
  270. data/lib/mongoid/collections.rb +0 -120
  271. data/lib/mongoid/config/database.rb +0 -181
  272. data/lib/mongoid/config/replset_database.rb +0 -80
  273. data/lib/mongoid/contexts/enumerable/sort.rb +0 -43
  274. data/lib/mongoid/contexts/enumerable.rb +0 -313
  275. data/lib/mongoid/contexts/mongo.rb +0 -485
  276. data/lib/mongoid/contexts.rb +0 -25
  277. data/lib/mongoid/criterion/builder.rb +0 -34
  278. data/lib/mongoid/criterion/complex.rb +0 -84
  279. data/lib/mongoid/criterion/creational.rb +0 -34
  280. data/lib/mongoid/criterion/exclusion.rb +0 -108
  281. data/lib/mongoid/criterion/inclusion.rb +0 -290
  282. data/lib/mongoid/criterion/optional.rb +0 -259
  283. data/lib/mongoid/criterion/selector.rb +0 -177
  284. data/lib/mongoid/cursor.rb +0 -88
  285. data/lib/mongoid/default_scope.rb +0 -36
  286. data/lib/mongoid/errors/invalid_type.rb +0 -25
  287. data/lib/mongoid/extensions/array/deep_copy.rb +0 -25
  288. data/lib/mongoid/extensions/array/deletion.rb +0 -29
  289. data/lib/mongoid/extensions/false_class/equality.rb +0 -26
  290. data/lib/mongoid/extensions/hash/criteria_helpers.rb +0 -47
  291. data/lib/mongoid/extensions/hash/deep_copy.rb +0 -25
  292. data/lib/mongoid/extensions/hash/scoping.rb +0 -25
  293. data/lib/mongoid/extensions/integer/checks.rb +0 -23
  294. data/lib/mongoid/extensions/nil/collectionization.rb +0 -23
  295. data/lib/mongoid/extensions/object/checks.rb +0 -29
  296. data/lib/mongoid/extensions/object/deep_copy.rb +0 -21
  297. data/lib/mongoid/extensions/object/reflections.rb +0 -48
  298. data/lib/mongoid/extensions/object/substitutable.rb +0 -15
  299. data/lib/mongoid/extensions/object/yoda.rb +0 -44
  300. data/lib/mongoid/extensions/object_id/conversions.rb +0 -60
  301. data/lib/mongoid/extensions/proc/scoping.rb +0 -25
  302. data/lib/mongoid/extensions/string/checks.rb +0 -36
  303. data/lib/mongoid/extensions/string/conversions.rb +0 -22
  304. data/lib/mongoid/extensions/string/inflections.rb +0 -118
  305. data/lib/mongoid/extensions/symbol/checks.rb +0 -23
  306. data/lib/mongoid/extensions/symbol/inflections.rb +0 -67
  307. data/lib/mongoid/extensions/true_class/equality.rb +0 -26
  308. data/lib/mongoid/extras.rb +0 -31
  309. data/lib/mongoid/fields/internal/array.rb +0 -76
  310. data/lib/mongoid/fields/internal/big_decimal.rb +0 -63
  311. data/lib/mongoid/fields/internal/bignum.rb +0 -10
  312. data/lib/mongoid/fields/internal/binary.rb +0 -11
  313. data/lib/mongoid/fields/internal/boolean.rb +0 -58
  314. data/lib/mongoid/fields/internal/date.rb +0 -51
  315. data/lib/mongoid/fields/internal/date_time.rb +0 -28
  316. data/lib/mongoid/fields/internal/false_class.rb +0 -10
  317. data/lib/mongoid/fields/internal/fixnum.rb +0 -10
  318. data/lib/mongoid/fields/internal/float.rb +0 -47
  319. data/lib/mongoid/fields/internal/foreign_keys/array.rb +0 -88
  320. data/lib/mongoid/fields/internal/foreign_keys/object.rb +0 -56
  321. data/lib/mongoid/fields/internal/hash.rb +0 -11
  322. data/lib/mongoid/fields/internal/integer.rb +0 -59
  323. data/lib/mongoid/fields/internal/localized.rb +0 -62
  324. data/lib/mongoid/fields/internal/nil_class.rb +0 -53
  325. data/lib/mongoid/fields/internal/object.rb +0 -11
  326. data/lib/mongoid/fields/internal/object_id.rb +0 -46
  327. data/lib/mongoid/fields/internal/range.rb +0 -61
  328. data/lib/mongoid/fields/internal/set.rb +0 -57
  329. data/lib/mongoid/fields/internal/string.rb +0 -42
  330. data/lib/mongoid/fields/internal/symbol.rb +0 -43
  331. data/lib/mongoid/fields/internal/time.rb +0 -23
  332. data/lib/mongoid/fields/internal/time_with_zone.rb +0 -23
  333. data/lib/mongoid/fields/internal/timekeeping.rb +0 -122
  334. data/lib/mongoid/fields/internal/true_class.rb +0 -10
  335. data/lib/mongoid/fields/mappings.rb +0 -42
  336. data/lib/mongoid/fields/serializable.rb +0 -270
  337. data/lib/mongoid/identity.rb +0 -92
  338. data/lib/mongoid/keys.rb +0 -144
  339. data/lib/mongoid/logger.rb +0 -45
  340. data/lib/mongoid/multi_database.rb +0 -31
  341. data/lib/mongoid/named_scope.rb +0 -166
  342. data/lib/mongoid/relations/embedded/atomic/operation.rb +0 -63
  343. data/lib/mongoid/relations/embedded/atomic/pull.rb +0 -65
  344. data/lib/mongoid/relations/embedded/atomic/push_all.rb +0 -59
  345. data/lib/mongoid/relations/embedded/atomic/set.rb +0 -61
  346. data/lib/mongoid/relations/embedded/atomic/unset.rb +0 -41
  347. data/lib/mongoid/relations/embedded/atomic.rb +0 -89
  348. data/lib/mongoid/relations/referenced/batch/insert.rb +0 -57
  349. data/lib/mongoid/relations/referenced/batch.rb +0 -73
  350. data/lib/mongoid/safety.rb +0 -105
  351. data/lib/mongoid/scope.rb +0 -31
@@ -0,0 +1,273 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Contextual
4
+ class MapReduce
5
+ include Enumerable
6
+ include Command
7
+
8
+ delegate :[], to: :results
9
+ delegate :==, :empty?, :inspect, to: :entries
10
+
11
+ # Get all the counts returned by the map/reduce.
12
+ #
13
+ # @example Get the counts.
14
+ # map_reduce.counts
15
+ #
16
+ # @return [ Hash ] The counts.
17
+ #
18
+ # @since 3.0.0
19
+ def counts
20
+ results["counts"]
21
+ end
22
+
23
+ # Iterates over each of the documents in the map/reduce, excluding the
24
+ # extra information that was passed back from the database.
25
+ #
26
+ # @example Iterate over the results.
27
+ # map_reduce.each do |doc|
28
+ # p doc
29
+ # end
30
+ #
31
+ # @return [ Enumerator ] The enumerator.
32
+ #
33
+ # @since 3.0.0
34
+ def each
35
+ if block_given?
36
+ documents.each do |doc|
37
+ yield doc
38
+ end
39
+ else
40
+ to_enum
41
+ end
42
+ end
43
+
44
+ # Get the number of documents emitted by the map/reduce.
45
+ #
46
+ # @example Get the emitted document count.
47
+ # map_reduce.emitted
48
+ #
49
+ # @return [ Integer ] The number of emitted documents.
50
+ #
51
+ # @since 3.0.0
52
+ def emitted
53
+ counts["emit"]
54
+ end
55
+
56
+ # Provide a finalize js function for the map/reduce.
57
+ #
58
+ # @example Provide a finalize function.
59
+ # map_reduce.finalize(func)
60
+ #
61
+ # @param [ String ] function The finalize function.
62
+ #
63
+ # @return [ MapReduce ] The map reduce.
64
+ #
65
+ # @since 3.0.0
66
+ def finalize(function)
67
+ command[:finalize] = function
68
+ self
69
+ end
70
+
71
+ # Initialize the new map/reduce directive.
72
+ #
73
+ # @example Initialize the new map/reduce.
74
+ # MapReduce.new(criteria, map, reduce)
75
+ #
76
+ # @param [ Criteria ] criteria The Mongoid criteria.
77
+ # @param [ String ] map The map js function.
78
+ # @param [ String ] reduce The reduce js function.
79
+ #
80
+ # @since 3.0.0
81
+ def initialize(criteria, map, reduce)
82
+ @criteria = criteria
83
+ command[:mapreduce] = criteria.klass.collection_name.to_s
84
+ command[:map], command[:reduce] = map, reduce
85
+ apply_criteria_options
86
+ end
87
+
88
+ # Get the number of documents that were input into the map/reduce.
89
+ #
90
+ # @example Get the count of input documents.
91
+ # map_reduce.input
92
+ #
93
+ # @return [ Integer ] The number of input documents.
94
+ #
95
+ # @since 3.0.0
96
+ def input
97
+ counts["input"]
98
+ end
99
+
100
+ # Sets the map/reduce to use jsMode.
101
+ #
102
+ # @example Set the map/reduce to jsMode.
103
+ # map_reduce.js_mode
104
+ #
105
+ # @return [ MapReduce ] The map/reduce.
106
+ #
107
+ # @since 3.0.0
108
+ def js_mode
109
+ command[:jsMode] = true
110
+ self
111
+ end
112
+
113
+ # Specifies where the map/reduce output is to be stored.
114
+ #
115
+ # @example Store output in memory.
116
+ # map_reduce.out(inline: 1)
117
+ #
118
+ # @example Store output in a collection, replacing existing documents.
119
+ # map_reduce.out(replace: "collection_name")
120
+ #
121
+ # @example Store output in a collection, merging existing documents.
122
+ # map_reduce.out(merge: "collection_name")
123
+ #
124
+ # @example Store output in a collection, reducing existing documents.
125
+ # map_reduce.out(reduce: "collection_name")
126
+ #
127
+ # @param [ Hash ] location The place to store the results.
128
+ #
129
+ # @return [ MapReduce ] The map/reduce object.
130
+ #
131
+ # @since 3.0.0
132
+ def out(location)
133
+ normalized = location.dup
134
+ normalized.update_values do |value|
135
+ value.is_a?(::Symbol) ? value.to_s : value
136
+ end
137
+ command[:out] = normalized
138
+ self
139
+ end
140
+
141
+ # Get the number of documents output by the map/reduce.
142
+ #
143
+ # @example Get the output document count.
144
+ # map_reduce.output
145
+ #
146
+ # @return [ Integer ] The number of output documents.
147
+ #
148
+ # @since 3.0.0
149
+ def output
150
+ counts["output"]
151
+ end
152
+
153
+ # Get the raw output from the map/reduce operation.
154
+ #
155
+ # @example Get the raw output.
156
+ # map_reduce.raw
157
+ #
158
+ # @return [ Hash ] The raw output.
159
+ #
160
+ # @since 3.0.0
161
+ def raw
162
+ results
163
+ end
164
+
165
+ # Get the number of documents reduced by the map/reduce.
166
+ #
167
+ # @example Get the reduced document count.
168
+ # map_reduce.reduced
169
+ #
170
+ # @return [ Integer ] The number of reduced documents.
171
+ #
172
+ # @since 3.0.0
173
+ def reduced
174
+ counts["reduce"]
175
+ end
176
+
177
+ # Adds a javascript object to the global scope of the map/reduce.
178
+ #
179
+ # @example Add an object to the global scope.
180
+ # map_reduce.scope(name: value)
181
+ #
182
+ # @param [ Hash ] object A hash of key/values for the global scope.
183
+ #
184
+ # @return [ MapReduce ]
185
+ #
186
+ # @since 3.0.0
187
+ def scope(object)
188
+ command[:scope] = object
189
+ self
190
+ end
191
+
192
+ # Get the execution time of the map/reduce.
193
+ #
194
+ # @example Get the execution time.
195
+ # map_reduce.time
196
+ #
197
+ # @return [ Float ] The time in milliseconds.
198
+ #
199
+ # @since 3.0.0
200
+ def time
201
+ results["timeMillis"]
202
+ end
203
+
204
+ private
205
+
206
+ # Apply criteria specific options - query, sort, limit.
207
+ #
208
+ # @api private
209
+ #
210
+ # @example Apply the criteria options
211
+ # map_reduce.apply_criteria_options
212
+ #
213
+ # @return [ nil ] Nothing.
214
+ #
215
+ # @since 3.0.0
216
+ def apply_criteria_options
217
+ command[:query] = criteria.selector
218
+ if sort = criteria.options[:sort]
219
+ command[:orderby] = sort
220
+ end
221
+ if limit = criteria.options[:limit]
222
+ command[:limit] = limit
223
+ end
224
+ end
225
+
226
+ # Get the result documents from the map/reduce. If the output was inline
227
+ # then we grab them from the results key. If the output was a temp
228
+ # collection then we need to execute a find on that collection.
229
+ #
230
+ # @api private
231
+ #
232
+ # @example Get the documents.
233
+ # map_reduce.documents
234
+ #
235
+ # @return [ Array, Cursor ] The documents.
236
+ #
237
+ # @since 3.0.0
238
+ def documents
239
+ return results["results"] if results.has_key?("results")
240
+ session[output_collection].find
241
+ end
242
+
243
+ # Get the collection that the map/reduce results were stored in.
244
+ #
245
+ # @api private
246
+ #
247
+ # @example Get the output collection.
248
+ # map_reduce.output_collection
249
+ #
250
+ # @return [ Symbol, String ] The output collection.
251
+ #
252
+ # @since 3.0.0
253
+ def output_collection
254
+ command[:out].values.first
255
+ end
256
+
257
+ # Execute the map/reduce command and get the results.
258
+ #
259
+ # @api private
260
+ #
261
+ # @example Get the results.
262
+ # map_reduce.results
263
+ #
264
+ # @return [ Hash ] The results of the command.
265
+ #
266
+ # @since 3.0.0
267
+ def results
268
+ raise Errors::NoMapReduceOutput.new(command) unless command[:out]
269
+ @results ||= session.command(command)
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,383 @@
1
+ # encoding: utf-8
2
+ require "mongoid/contextual/aggregable/memory"
3
+
4
+ module Mongoid
5
+ module Contextual
6
+ class Memory
7
+ include Enumerable
8
+ include Aggregable::Memory
9
+
10
+ # @attribute [r] collection The root collection.
11
+ # @attribute [r] criteria The criteria for the context.
12
+ # @attribute [r] klass The criteria class.
13
+ # @attribute [r] root The root document.
14
+ # @attribute [r] path The atomic path.
15
+ # @attribute [r] selector The root document selector.
16
+ # @attribute [r] matching The in memory documents that match the selector.
17
+ attr_reader \
18
+ :collection,
19
+ :criteria,
20
+ :documents,
21
+ :klass,
22
+ :path,
23
+ :root,
24
+ :selector
25
+
26
+ # Check if the context is equal to the other object.
27
+ #
28
+ # @example Check equality.
29
+ # context == []
30
+ #
31
+ # @param [ Array ] other The other array.
32
+ #
33
+ # @return [ true, false ] If the objects are equal.
34
+ #
35
+ # @since 3.0.0
36
+ def ==(other)
37
+ return false unless other.respond_to?(:entries)
38
+ entries == other.entries
39
+ end
40
+
41
+ # Is the enumerable of matching documents empty?
42
+ #
43
+ # @example Is the context empty?
44
+ # context.blank?
45
+ #
46
+ # @return [ true, false ] If the context is empty.
47
+ #
48
+ # @since 3.0.0
49
+ def blank?
50
+ count == 0
51
+ end
52
+ alias :empty? :blank?
53
+
54
+ # Delete all documents in the database that match the selector.
55
+ #
56
+ # @example Delete all the documents.
57
+ # context.delete
58
+ #
59
+ # @return [ nil ] Nil.
60
+ #
61
+ # @since 3.0.0
62
+ def delete
63
+ deleted = count
64
+ removed = map do |doc|
65
+ prepare_remove(doc)
66
+ doc.as_document
67
+ end
68
+ unless removed.empty?
69
+ collection.find(selector).update("$pullAll" => { path => removed })
70
+ end
71
+ deleted
72
+ end
73
+ alias :delete_all :delete
74
+
75
+ # Destroy all documents in the database that match the selector.
76
+ #
77
+ # @example Destroy all the documents.
78
+ # context.destroy
79
+ #
80
+ # @return [ nil ] Nil.
81
+ #
82
+ # @since 3.0.0
83
+ def destroy
84
+ deleted = count
85
+ each do |doc|
86
+ documents.delete_one(doc)
87
+ doc.destroy
88
+ end
89
+ deleted
90
+ end
91
+ alias :destroy_all :destroy
92
+
93
+ # Get the distinct values in the db for the provided field.
94
+ #
95
+ # @example Get the distinct values.
96
+ # context.distinct(:name)
97
+ #
98
+ # @param [ String, Symbol ] field The name of the field.
99
+ #
100
+ # @return [ Array<Object> ] The distinct values for the field.
101
+ #
102
+ # @since 3.0.0
103
+ def distinct(field)
104
+ documents.map{ |doc| doc.send(field) }.uniq
105
+ end
106
+
107
+ # Iterate over the context. If provided a block, yield to a Mongoid
108
+ # document for each, otherwise return an enum.
109
+ #
110
+ # @example Iterate over the context.
111
+ # context.each do |doc|
112
+ # puts doc.name
113
+ # end
114
+ #
115
+ # @return [ Enumerator ] The enumerator.
116
+ #
117
+ # @since 3.0.0
118
+ def each
119
+ if block_given?
120
+ documents[skipping || 0, limiting || documents.length].each do |doc|
121
+ yield doc
122
+ end
123
+ else
124
+ to_enum
125
+ end
126
+ end
127
+
128
+ # Do any documents exist for the context.
129
+ #
130
+ # @example Do any documents exist for the context.
131
+ # context.exists?
132
+ #
133
+ # @return [ true, false ] If the count is more than zero.
134
+ #
135
+ # @since 3.0.0
136
+ def exists?
137
+ count > 0
138
+ end
139
+
140
+ # Get the first document in the database for the criteria's selector.
141
+ #
142
+ # @example Get the first document.
143
+ # context.first
144
+ #
145
+ # @return [ Document ] The first document.
146
+ #
147
+ # @since 3.0.0
148
+ def first
149
+ documents.first
150
+ end
151
+ alias :one :first
152
+
153
+ # Create the new in memory context.
154
+ #
155
+ # @example Create the new context.
156
+ # Memory.new(criteria)
157
+ #
158
+ # @param [ Criteria ] The criteria.
159
+ #
160
+ # @since 3.0.0
161
+ def initialize(criteria)
162
+ @criteria, @klass = criteria, criteria.klass
163
+ @documents = criteria.documents.select do |doc|
164
+ @root ||= doc._root
165
+ @collection ||= root.collection
166
+ doc.matches?(criteria.selector)
167
+ end
168
+ apply_sorting
169
+ apply_options
170
+ end
171
+
172
+ # Get the last document in the database for the criteria's selector.
173
+ #
174
+ # @example Get the last document.
175
+ # context.last
176
+ #
177
+ # @return [ Document ] The last document.
178
+ #
179
+ # @since 3.0.0
180
+ def last
181
+ documents.last
182
+ end
183
+
184
+ # Get the length of matching documents in the context.
185
+ #
186
+ # @example Get the length of matching documents.
187
+ # context.length
188
+ #
189
+ # @return [ Integer ] The matching length.
190
+ #
191
+ # @since 3.0.0
192
+ def length
193
+ documents.length
194
+ end
195
+ alias :size :length
196
+
197
+ # Limits the number of documents that are returned.
198
+ #
199
+ # @example Limit the documents.
200
+ # context.limit(20)
201
+ #
202
+ # @param [ Integer ] value The number of documents to return.
203
+ #
204
+ # @return [ Mongo ] The context.
205
+ #
206
+ # @since 3.0.0
207
+ def limit(value)
208
+ self.limiting = value
209
+ self
210
+ end
211
+
212
+ # Skips the provided number of documents.
213
+ #
214
+ # @example Skip the documents.
215
+ # context.skip(20)
216
+ #
217
+ # @param [ Integer ] value The number of documents to skip.
218
+ #
219
+ # @return [ Mongo ] The context.
220
+ #
221
+ # @since 3.0.0
222
+ def skip(value)
223
+ self.skipping = value
224
+ self
225
+ end
226
+
227
+ # Sorts the documents by the provided spec.
228
+ #
229
+ # @example Sort the documents.
230
+ # context.sort(name: -1, title: 1)
231
+ #
232
+ # @param [ Hash ] values The sorting values as field/direction(1/-1)
233
+ # pairs.
234
+ #
235
+ # @return [ Mongo ] The context.
236
+ #
237
+ # @since 3.0.0
238
+ def sort(values)
239
+ in_place_sort(values) and self
240
+ end
241
+
242
+ # Update all the matching documents atomically.
243
+ #
244
+ # @example Update all the matching documents.
245
+ # context.update(name: "Smiths")
246
+ #
247
+ # @param [ Hash ] attributes The new attributes for each document.
248
+ #
249
+ # @return [ nil, false ] False if no attributes were provided.
250
+ #
251
+ # @since 3.0.0
252
+ def update(attributes = nil)
253
+ return false unless attributes
254
+ updates = {}
255
+ each do |doc|
256
+ @selector ||= root.atomic_selector
257
+ doc.write_attributes(attributes)
258
+ updates.merge!(doc.atomic_position => attributes)
259
+ end
260
+ collection.find(selector).update("$set" => updates)
261
+ end
262
+ alias :update_all :update
263
+
264
+ private
265
+
266
+ # Get the limiting value.
267
+ #
268
+ # @api private
269
+ #
270
+ # @example Get the limiting value.
271
+ #
272
+ # @return [ Integer ] The limit.
273
+ #
274
+ # @since 3.0.0
275
+ def limiting
276
+ defined?(@limiting) ? @limiting : nil
277
+ end
278
+
279
+ # Set the limiting value.
280
+ #
281
+ # @api private
282
+ #
283
+ # @example Set the limiting value.
284
+ #
285
+ # @param [ Integer ] value The limit.
286
+ #
287
+ # @return [ Integer ] The limit.
288
+ #
289
+ # @since 3.0.0
290
+ def limiting=(value)
291
+ @limiting = value
292
+ end
293
+
294
+ # Get the skiping value.
295
+ #
296
+ # @api private
297
+ #
298
+ # @example Get the skiping value.
299
+ #
300
+ # @return [ Integer ] The skip.
301
+ #
302
+ # @since 3.0.0
303
+ def skipping
304
+ defined?(@skipping) ? @skipping : nil
305
+ end
306
+
307
+ # Set the skiping value.
308
+ #
309
+ # @api private
310
+ #
311
+ # @example Set the skiping value.
312
+ #
313
+ # @param [ Integer ] value The skip.
314
+ #
315
+ # @return [ Integer ] The skip.
316
+ #
317
+ # @since 3.0.0
318
+ def skipping=(value)
319
+ @skipping = value
320
+ end
321
+
322
+ # Apply criteria options.
323
+ #
324
+ # @api private
325
+ #
326
+ # @example Apply criteria options.
327
+ # context.apply_options
328
+ #
329
+ # @return [ Memory ] self.
330
+ #
331
+ # @since 3.0.0
332
+ def apply_options
333
+ skip(criteria.options[:skip]).limit(criteria.options[:limit])
334
+ end
335
+
336
+ # Map the sort symbols to the correct MongoDB values.
337
+ #
338
+ # @example Apply the sorting params.
339
+ # context.apply_sorting
340
+ #
341
+ # @since 3.0.0
342
+ def apply_sorting
343
+ if spec = criteria.options[:sort]
344
+ in_place_sort(spec)
345
+ end
346
+ end
347
+
348
+ # Sort the documents in place.
349
+ #
350
+ # @example Sort the documents.
351
+ # context.in_place_sort(name: 1)
352
+ #
353
+ # @param [ Hash ] values The field/direction sorting pairs.
354
+ #
355
+ # @since 3.0.0
356
+ def in_place_sort(values)
357
+ values.each_pair do |field, dir|
358
+ documents.sort! do |a, b|
359
+ dir > 0 ? a[field] <=> b[field] : b[field] <=> a[field]
360
+ end
361
+ end
362
+ end
363
+
364
+ # Prepare the document for batch removal.
365
+ #
366
+ # @api private
367
+ #
368
+ # @example Prepare for removal.
369
+ # context.prepare_remove(doc)
370
+ #
371
+ # @param [ Document ] doc The document.
372
+ #
373
+ # @since 3.0.0
374
+ def prepare_remove(doc)
375
+ @selector ||= root.atomic_selector
376
+ @path ||= doc.atomic_path
377
+ documents.delete_one(doc)
378
+ doc._parent.remove_child(doc)
379
+ doc.destroyed = true
380
+ end
381
+ end
382
+ end
383
+ end