mongoid 2.8.1 → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (351) hide show
  1. data/CHANGELOG.md +802 -58
  2. data/LICENSE +1 -1
  3. data/README.md +10 -11
  4. data/Rakefile +2 -8
  5. data/lib/config/locales/en.yml +441 -51
  6. data/lib/mongoid.rb +24 -39
  7. data/lib/mongoid/atomic.rb +16 -33
  8. data/lib/mongoid/atomic/modifiers.rb +2 -2
  9. data/lib/mongoid/atomic/paths/embedded.rb +4 -5
  10. data/lib/mongoid/atomic/paths/embedded/many.rb +6 -6
  11. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -5
  12. data/lib/mongoid/atomic/paths/root.rb +4 -5
  13. data/lib/mongoid/attributes.rb +95 -32
  14. data/lib/mongoid/attributes/processing.rb +14 -10
  15. data/lib/mongoid/attributes/readonly.rb +56 -0
  16. data/lib/mongoid/callbacks.rb +90 -27
  17. data/lib/mongoid/collections/retry.rb +2 -3
  18. data/lib/mongoid/components.rb +11 -23
  19. data/lib/mongoid/config.rb +87 -233
  20. data/lib/mongoid/config/environment.rb +5 -6
  21. data/lib/mongoid/config/inflections.rb +6 -0
  22. data/lib/mongoid/config/options.rb +1 -1
  23. data/lib/mongoid/config/validators.rb +3 -0
  24. data/lib/mongoid/config/validators/option.rb +25 -0
  25. data/lib/mongoid/config/validators/session.rb +140 -0
  26. data/lib/mongoid/contextual.rb +50 -0
  27. data/lib/mongoid/contextual/aggregable/memory.rb +98 -0
  28. data/lib/mongoid/contextual/aggregable/mongo.rb +181 -0
  29. data/lib/mongoid/contextual/atomic.rb +179 -0
  30. data/lib/mongoid/contextual/command.rb +43 -0
  31. data/lib/mongoid/contextual/find_and_modify.rb +66 -0
  32. data/lib/mongoid/contextual/map_reduce.rb +273 -0
  33. data/lib/mongoid/contextual/memory.rb +383 -0
  34. data/lib/mongoid/contextual/mongo.rb +543 -0
  35. data/lib/mongoid/copyable.rb +3 -34
  36. data/lib/mongoid/criteria.rb +436 -250
  37. data/lib/mongoid/criterion/inspection.rb +14 -8
  38. data/lib/mongoid/criterion/scoping.rb +114 -44
  39. data/lib/mongoid/dirty.rb +152 -67
  40. data/lib/mongoid/document.rb +69 -50
  41. data/lib/mongoid/errors.rb +22 -1
  42. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  43. data/lib/mongoid/errors/callback.rb +5 -6
  44. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  45. data/lib/mongoid/errors/document_not_found.rb +98 -17
  46. data/lib/mongoid/errors/eager_load.rb +3 -6
  47. data/lib/mongoid/errors/invalid_collection.rb +3 -3
  48. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  49. data/lib/mongoid/errors/invalid_database.rb +3 -3
  50. data/lib/mongoid/errors/invalid_field.rb +54 -8
  51. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  52. data/lib/mongoid/errors/invalid_find.rb +3 -3
  53. data/lib/mongoid/errors/invalid_index.rb +28 -0
  54. data/lib/mongoid/errors/invalid_options.rb +4 -4
  55. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  56. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  57. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  58. data/lib/mongoid/errors/invalid_time.rb +3 -6
  59. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  60. data/lib/mongoid/errors/mixed_relations.rb +4 -9
  61. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  62. data/lib/mongoid/errors/mongoid_error.rb +54 -3
  63. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  64. data/lib/mongoid/errors/no_default_session.rb +23 -0
  65. data/lib/mongoid/errors/no_environment.rb +3 -3
  66. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  67. data/lib/mongoid/errors/no_parent.rb +24 -0
  68. data/lib/mongoid/errors/no_session_config.rb +22 -0
  69. data/lib/mongoid/errors/no_session_database.rb +27 -0
  70. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  71. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  72. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  73. data/lib/mongoid/errors/scope_overwrite.rb +4 -4
  74. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +4 -4
  75. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  76. data/lib/mongoid/errors/unsaved_document.rb +4 -8
  77. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  78. data/lib/mongoid/errors/unsupported_version.rb +4 -4
  79. data/lib/mongoid/errors/validations.rb +7 -6
  80. data/lib/mongoid/errors/versioning_not_on_root.rb +23 -0
  81. data/lib/mongoid/extensions.rb +28 -76
  82. data/lib/mongoid/extensions/array.rb +127 -0
  83. data/lib/mongoid/extensions/big_decimal.rb +42 -0
  84. data/lib/mongoid/extensions/boolean.rb +24 -0
  85. data/lib/mongoid/extensions/date.rb +70 -0
  86. data/lib/mongoid/extensions/date_time.rb +68 -0
  87. data/lib/mongoid/extensions/false_class.rb +26 -0
  88. data/lib/mongoid/extensions/float.rb +44 -0
  89. data/lib/mongoid/extensions/hash.rb +91 -0
  90. data/lib/mongoid/extensions/integer.rb +54 -0
  91. data/lib/mongoid/extensions/module.rb +28 -0
  92. data/lib/mongoid/extensions/nil_class.rb +21 -0
  93. data/lib/mongoid/extensions/object.rb +188 -0
  94. data/lib/mongoid/extensions/object_id.rb +53 -0
  95. data/lib/mongoid/extensions/range.rb +55 -0
  96. data/lib/mongoid/extensions/regexp.rb +27 -0
  97. data/lib/mongoid/extensions/set.rb +55 -0
  98. data/lib/mongoid/extensions/string.rb +155 -0
  99. data/lib/mongoid/extensions/symbol.rb +54 -0
  100. data/lib/mongoid/extensions/time.rb +78 -0
  101. data/lib/mongoid/extensions/time_with_zone.rb +55 -0
  102. data/lib/mongoid/extensions/true_class.rb +26 -0
  103. data/lib/mongoid/factory.rb +1 -1
  104. data/lib/mongoid/fields.rb +129 -194
  105. data/lib/mongoid/fields/foreign_key.rb +134 -0
  106. data/lib/mongoid/fields/localized.rb +73 -0
  107. data/lib/mongoid/fields/standard.rb +268 -0
  108. data/lib/mongoid/fields/validators.rb +2 -0
  109. data/lib/mongoid/fields/validators/macro.rb +83 -0
  110. data/lib/mongoid/finders.rb +42 -43
  111. data/lib/mongoid/hierarchy.rb +25 -14
  112. data/lib/mongoid/identity_map.rb +31 -19
  113. data/lib/mongoid/indexes.rb +66 -15
  114. data/lib/mongoid/indexes/validators/options.rb +80 -0
  115. data/lib/mongoid/inspection.rb +1 -1
  116. data/lib/mongoid/javascript.rb +1 -1
  117. data/lib/mongoid/json.rb +2 -2
  118. data/lib/mongoid/loggable.rb +69 -0
  119. data/lib/mongoid/matchers.rb +1 -1
  120. data/lib/mongoid/matchers/all.rb +7 -8
  121. data/lib/mongoid/matchers/and.rb +3 -3
  122. data/lib/mongoid/matchers/default.rb +6 -4
  123. data/lib/mongoid/matchers/exists.rb +2 -2
  124. data/lib/mongoid/matchers/gt.rb +2 -2
  125. data/lib/mongoid/matchers/gte.rb +2 -2
  126. data/lib/mongoid/matchers/in.rb +3 -7
  127. data/lib/mongoid/matchers/lt.rb +2 -2
  128. data/lib/mongoid/matchers/lte.rb +2 -2
  129. data/lib/mongoid/matchers/ne.rb +2 -2
  130. data/lib/mongoid/matchers/nin.rb +2 -2
  131. data/lib/mongoid/matchers/or.rb +2 -2
  132. data/lib/mongoid/matchers/size.rb +2 -2
  133. data/lib/mongoid/matchers/strategies.rb +3 -3
  134. data/lib/mongoid/multi_parameter_attributes.rb +8 -10
  135. data/lib/mongoid/nested_attributes.rb +17 -9
  136. data/lib/mongoid/observer.rb +1 -2
  137. data/lib/mongoid/paranoia.rb +13 -18
  138. data/lib/mongoid/persistence.rb +43 -39
  139. data/lib/mongoid/persistence/atomic.rb +2 -2
  140. data/lib/mongoid/persistence/atomic/add_to_set.rb +5 -9
  141. data/lib/mongoid/persistence/atomic/bit.rb +5 -7
  142. data/lib/mongoid/persistence/atomic/inc.rb +5 -7
  143. data/lib/mongoid/persistence/atomic/operation.rb +45 -6
  144. data/lib/mongoid/persistence/atomic/pop.rb +5 -7
  145. data/lib/mongoid/persistence/atomic/pull.rb +5 -7
  146. data/lib/mongoid/persistence/atomic/pull_all.rb +5 -7
  147. data/lib/mongoid/persistence/atomic/push.rb +4 -10
  148. data/lib/mongoid/persistence/atomic/push_all.rb +4 -10
  149. data/lib/mongoid/persistence/atomic/rename.rb +6 -7
  150. data/lib/mongoid/persistence/atomic/sets.rb +5 -7
  151. data/lib/mongoid/persistence/atomic/unset.rb +4 -5
  152. data/lib/mongoid/persistence/deletion.rb +2 -2
  153. data/lib/mongoid/persistence/insertion.rb +10 -16
  154. data/lib/mongoid/persistence/modification.rb +5 -9
  155. data/lib/mongoid/persistence/operations.rb +6 -19
  156. data/lib/mongoid/persistence/operations/embedded/insert.rb +7 -6
  157. data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -5
  158. data/lib/mongoid/persistence/operations/insert.rb +4 -4
  159. data/lib/mongoid/persistence/operations/remove.rb +4 -4
  160. data/lib/mongoid/persistence/operations/update.rb +5 -5
  161. data/lib/mongoid/railtie.rb +26 -11
  162. data/lib/mongoid/railties/database.rake +22 -108
  163. data/lib/mongoid/relations.rb +4 -6
  164. data/lib/mongoid/relations/accessors.rb +119 -19
  165. data/lib/mongoid/relations/auto_save.rb +59 -5
  166. data/lib/mongoid/relations/binding.rb +211 -2
  167. data/lib/mongoid/relations/bindings/embedded/in.rb +16 -22
  168. data/lib/mongoid/relations/bindings/embedded/many.rb +9 -50
  169. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -16
  170. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -57
  171. data/lib/mongoid/relations/bindings/referenced/many.rb +8 -20
  172. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -19
  173. data/lib/mongoid/relations/bindings/referenced/one.rb +10 -24
  174. data/lib/mongoid/relations/builder.rb +3 -3
  175. data/lib/mongoid/relations/builders.rb +19 -16
  176. data/lib/mongoid/relations/builders/embedded/in.rb +5 -5
  177. data/lib/mongoid/relations/builders/embedded/many.rb +12 -12
  178. data/lib/mongoid/relations/builders/embedded/one.rb +6 -6
  179. data/lib/mongoid/relations/builders/nested_attributes/many.rb +8 -8
  180. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -4
  181. data/lib/mongoid/relations/builders/referenced/in.rb +4 -4
  182. data/lib/mongoid/relations/builders/referenced/many.rb +5 -5
  183. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +7 -5
  184. data/lib/mongoid/relations/builders/referenced/one.rb +5 -5
  185. data/lib/mongoid/relations/cascading.rb +6 -4
  186. data/lib/mongoid/relations/cascading/delete.rb +3 -5
  187. data/lib/mongoid/relations/cascading/destroy.rb +3 -3
  188. data/lib/mongoid/relations/cascading/nullify.rb +3 -3
  189. data/lib/mongoid/relations/cascading/restrict.rb +37 -0
  190. data/lib/mongoid/relations/constraint.rb +4 -3
  191. data/lib/mongoid/relations/conversions.rb +5 -6
  192. data/lib/mongoid/relations/cyclic.rb +7 -7
  193. data/lib/mongoid/relations/embedded/batchable.rb +346 -0
  194. data/lib/mongoid/relations/embedded/in.rb +23 -12
  195. data/lib/mongoid/relations/embedded/many.rb +99 -161
  196. data/lib/mongoid/relations/embedded/one.rb +25 -14
  197. data/lib/mongoid/relations/macros.rb +105 -61
  198. data/lib/mongoid/relations/many.rb +93 -14
  199. data/lib/mongoid/relations/metadata.rb +200 -45
  200. data/lib/mongoid/relations/nested_builder.rb +3 -5
  201. data/lib/mongoid/relations/one.rb +2 -2
  202. data/lib/mongoid/relations/options.rb +2 -2
  203. data/lib/mongoid/relations/polymorphic.rb +9 -9
  204. data/lib/mongoid/relations/proxy.rb +60 -31
  205. data/lib/mongoid/relations/referenced/in.rb +40 -15
  206. data/lib/mongoid/relations/referenced/many.rb +117 -132
  207. data/lib/mongoid/relations/referenced/many_to_many.rb +101 -46
  208. data/lib/mongoid/relations/referenced/one.rb +34 -13
  209. data/lib/mongoid/relations/reflections.rb +3 -3
  210. data/lib/mongoid/relations/synchronization.rb +19 -23
  211. data/lib/mongoid/relations/targets/enumerable.rb +86 -57
  212. data/lib/mongoid/reloading.rb +12 -14
  213. data/lib/mongoid/scoping.rb +329 -0
  214. data/lib/mongoid/serialization.rb +8 -27
  215. data/lib/mongoid/sessions.rb +359 -0
  216. data/lib/mongoid/sessions/factory.rb +106 -0
  217. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  218. data/lib/mongoid/sessions/validators.rb +2 -0
  219. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  220. data/lib/mongoid/sharding.rb +6 -6
  221. data/lib/mongoid/state.rb +6 -7
  222. data/lib/mongoid/threaded.rb +167 -59
  223. data/lib/mongoid/threaded/lifecycle.rb +21 -22
  224. data/lib/mongoid/threaded/sessions.rb +0 -0
  225. data/lib/mongoid/timestamps.rb +1 -1
  226. data/lib/mongoid/timestamps/created.rb +8 -4
  227. data/lib/mongoid/timestamps/timeless.rb +6 -4
  228. data/lib/mongoid/timestamps/updated.rb +3 -3
  229. data/lib/mongoid/unit_of_work.rb +61 -0
  230. data/lib/mongoid/validations.rb +27 -19
  231. data/lib/mongoid/validations/associated.rb +2 -2
  232. data/lib/mongoid/validations/format.rb +2 -2
  233. data/lib/mongoid/validations/presence.rb +31 -5
  234. data/lib/mongoid/validations/uniqueness.rb +9 -12
  235. data/lib/mongoid/version.rb +2 -2
  236. data/lib/mongoid/versioning.rb +25 -26
  237. data/lib/rack/mongoid/middleware/identity_map.rb +3 -3
  238. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -1
  239. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +59 -19
  240. data/lib/rails/generators/mongoid/model/model_generator.rb +7 -7
  241. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +2 -2
  242. data/lib/rails/generators/mongoid/observer/observer_generator.rb +4 -4
  243. data/lib/rails/generators/mongoid_generator.rb +5 -5
  244. data/lib/rails/mongoid.rb +69 -25
  245. metadata +110 -137
  246. checksums.yaml +0 -7
  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.rb +0 -120
  269. data/lib/mongoid/collections/master.rb +0 -45
  270. data/lib/mongoid/collections/operations.rb +0 -44
  271. data/lib/mongoid/config/database.rb +0 -181
  272. data/lib/mongoid/config/replset_database.rb +0 -80
  273. data/lib/mongoid/contexts.rb +0 -25
  274. data/lib/mongoid/contexts/enumerable.rb +0 -313
  275. data/lib/mongoid/contexts/enumerable/sort.rb +0 -43
  276. data/lib/mongoid/contexts/mongo.rb +0 -487
  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 -110
  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 -77
  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 -36
  341. data/lib/mongoid/named_scope.rb +0 -166
  342. data/lib/mongoid/relations/embedded/atomic.rb +0 -89
  343. data/lib/mongoid/relations/embedded/atomic/operation.rb +0 -63
  344. data/lib/mongoid/relations/embedded/atomic/pull.rb +0 -65
  345. data/lib/mongoid/relations/embedded/atomic/push_all.rb +0 -59
  346. data/lib/mongoid/relations/embedded/atomic/set.rb +0 -61
  347. data/lib/mongoid/relations/embedded/atomic/unset.rb +0 -41
  348. data/lib/mongoid/relations/referenced/batch.rb +0 -73
  349. data/lib/mongoid/relations/referenced/batch/insert.rb +0 -57
  350. data/lib/mongoid/safety.rb +0 -105
  351. data/lib/mongoid/scope.rb +0 -31
@@ -1,43 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Contexts #:nodoc:
4
- class Enumerable
5
- class Sort
6
- attr_reader :value, :direction
7
-
8
- # Create a new sorting object. This requires a value and a sort
9
- # direction of +:asc+ or +:desc+.
10
- def initialize(value, direction)
11
- @value = value
12
- @direction = direction
13
- end
14
-
15
- # Return +true+ if the direction is +:asc+, otherwise false.
16
- def ascending?
17
- direction == :asc
18
- end
19
-
20
- # Compare two +Sort+ objects against each other, taking into
21
- # consideration the direction of the sorting.
22
- def <=>(other)
23
- cmp = compare(value, other.value)
24
- ascending? ? cmp : cmp * -1
25
- end
26
-
27
- private
28
-
29
- # Compare two values allowing for nil values.
30
- def compare(a, b)
31
- case
32
- when a.nil?
33
- b.nil? ? 0 : 1
34
- when b.nil?
35
- -1
36
- else
37
- a <=> b
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,487 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Contexts #:nodoc:
4
- class Mongo
5
- attr_accessor :criteria
6
-
7
- delegate :cached?, :klass, :options, :field_list, :selector, :to => :criteria
8
- delegate :collection, :to => :klass
9
-
10
- # Perform an add to set on the matching documents.
11
- #
12
- # @example Add to set on all matching.
13
- # Person.where(:name => "Alex").add_to_set(:aliases, "value")
14
- #
15
- # @param [ String ] field The field to add to.
16
- # @param [ Object ] value The value to add.
17
- #
18
- # @return [ Object ] The update value.
19
- #
20
- # @since 2.1.0
21
- def add_to_set(field, value)
22
- klass.collection.update(
23
- selector,
24
- { "$addToSet" => { field => value } },
25
- :multi => true
26
- )
27
- end
28
-
29
- # Aggregate the context. This will take the internally built selector and options
30
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
31
- # collection itself will be retrieved from the class provided, and once the
32
- # query has returned it will provided a grouping of keys with counts.
33
- #
34
- # @example Aggreate the context.
35
- # context.aggregate
36
- #
37
- # @return [ Hash ] A +Hash+ with field values as keys, counts as values
38
- def aggregate
39
- klass.collection.group(
40
- :key => field_list,
41
- :cond => selector,
42
- :initial => { :count => 0 },
43
- :reduce => Javascript.aggregate
44
- )
45
- end
46
-
47
- # Get the average value for the supplied field.
48
- #
49
- # This will take the internally built selector and options
50
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
51
- # collection itself will be retrieved from the class provided, and once the
52
- # query has returned it will provided a grouping of keys with averages.
53
- #
54
- # @example Get the average for a field.
55
- # context.avg(:age)
56
- #
57
- # @param [ Symbol ] field The field to get the average for.
58
- #
59
- # @return [ Numeric ] A numeric value that is the average.
60
- def avg(field)
61
- total = sum(field)
62
- total ? (total / count) : nil
63
- end
64
-
65
- # Determine if the context is empty or blank given the criteria. Will
66
- # perform a quick has_one asking only for the id.
67
- #
68
- # @example Is the context empty?
69
- # context.blank?a
70
- #
71
- # @return [ true, false ] True if blank.
72
- def blank?
73
- klass.collection.find_one(selector, { :fields => [ :_id ] }).nil?
74
- end
75
- alias :empty? :blank?
76
-
77
- # Get the count of matching documents in the database for the context.
78
- #
79
- # @example Get the count without skip and limit taken into consideration.
80
- # context.count
81
- #
82
- # @example Get the count with skip and limit applied.
83
- # context.count(true)
84
- #
85
- # @param [Boolean] extras True to inclued previous skip/limit
86
- # statements in the count; false to ignore them. Defaults to `false`.
87
- #
88
- # @return [ Integer ] The count of documents.
89
- def count(extras = false)
90
- if cached?
91
- @count ||= collection.find(selector, process_options).count(extras)
92
- else
93
- collection.find(selector, process_options).count(extras)
94
- end
95
- end
96
- alias :size :count
97
- alias :length :count
98
-
99
- # Delete all the documents in the database matching the selector.
100
- #
101
- # @example Delete the documents.
102
- # context.delete_all
103
- #
104
- # @return [ Integer ] The number of documents deleted.
105
- #
106
- # @since 2.0.0.rc.1
107
- def delete_all
108
- klass.delete_all(:conditions => selector)
109
- end
110
- alias :delete :delete_all
111
-
112
- # Destroy all the documents in the database matching the selector.
113
- #
114
- # @example Destroy the documents.
115
- # context.destroy_all
116
- #
117
- # @return [ Integer ] The number of documents destroyed.
118
- #
119
- # @since 2.0.0.rc.1
120
- def destroy_all
121
- klass.destroy_all(:conditions => selector)
122
- end
123
- alias :destroy :destroy_all
124
-
125
- # Gets an array of distinct values for the supplied field across the
126
- # entire collection or the susbset given the criteria.
127
- #
128
- # @example Get the distinct values.
129
- # context.distinct(:title)
130
- #
131
- # @param [ Symbol ] field The field to get the values for.
132
- #
133
- # @return [ Array<Object> ] The distinct values for the field.
134
- def distinct(field)
135
- klass.collection.distinct(field, selector)
136
- end
137
-
138
- # Eager load the inclusions for the provided documents.
139
- #
140
- # @example Eager load the inclusions.
141
- # context.eager_load(docs)
142
- #
143
- # @param [ Array<Document> ] docs The docs returning from the db.
144
- #
145
- # @since 2.4.1
146
- def eager_load(docs)
147
- criteria.inclusions.reject! do |metadata|
148
- unless docs.empty?
149
- parent_ids = docs.map(&:id)
150
- if metadata.macro == :referenced_in
151
- child_ids = load_ids(metadata.foreign_key)
152
- metadata.eager_load(child_ids)
153
- else
154
- metadata.eager_load(parent_ids)
155
- end
156
- end
157
- end
158
- end
159
-
160
- # Execute the context. This will take the selector and options
161
- # and pass them on to the Ruby driver's +find()+ method on the collection. The
162
- # collection itself will be retrieved from the class provided, and once the
163
- # query has returned new documents of the type of class provided will be instantiated.
164
- #
165
- # @example Execute the criteria on the context.
166
- # context.execute
167
- #
168
- # @return [ Cursor ] An enumerable +Cursor+ of results.
169
- def execute
170
- collection, options = klass.collection, process_options
171
- if criteria.inclusions.any?
172
- collection.find(selector, options).entries.tap do |docs|
173
- eager_load(docs)
174
- end
175
- else
176
- collection.find(selector, options)
177
- end
178
- end
179
-
180
- # Loads an array of ids only for the current criteria. Used by eager
181
- # loading to determine the documents to load.
182
- #
183
- # @example Load the related ids.
184
- # criteria.load_ids("person_id")
185
- #
186
- # @param [ String ] key The id or foriegn key string.
187
- #
188
- # @return [ Array<String, BSON::ObjectId> ] The ids to load.
189
- #
190
- # @since 2.2.0
191
- def load_ids(key)
192
- klass.collection.driver.find(
193
- selector,
194
- process_options.merge({ :fields => { key => 1 }})
195
- ).map { |doc| doc[key] }
196
- end
197
-
198
- # Return the first result for the +Context+.
199
- #
200
- # @example Get the first document.
201
- # context.one
202
- #
203
- # @return [ Document ] The first document in the collection.
204
- def first
205
- attributes = klass.collection.find_one(selector, options_with_default_sorting)
206
- return nil unless attributes
207
- selecting do
208
- Mongoid::Factory.from_db(klass, attributes).tap do |doc|
209
- eager_load([ doc ]) if criteria.inclusions.any?
210
- end
211
- end
212
- end
213
- alias :one :first
214
-
215
- # Groups the context. This will take the internally built selector and options
216
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
217
- # collection itself will be retrieved from the class provided, and once the
218
- # query has returned it will provided a grouping of keys with objects.
219
- #
220
- # @example Get the criteria as a group.
221
- # context.group
222
- #
223
- # @return [ Hash ] Hash with field values as keys, arrays of documents as values.
224
- def group
225
- klass.collection.group(
226
- :key => field_list,
227
- :cond => selector,
228
- :initial => { :group => [] },
229
- :reduce => Javascript.group
230
- ).collect do |docs|
231
- docs["group"] = docs["group"].collect do |attrs|
232
- Mongoid::Factory.from_db(klass, attrs)
233
- end
234
- docs
235
- end
236
- end
237
-
238
- # Create the new mongo context. This will execute the queries given the
239
- # selector and options against the database.
240
- #
241
- # @example Create a new context.
242
- # Mongoid::Contexts::Mongo.new(criteria)
243
- #
244
- # @param [ Criteria ] criteria The criteria to create with.
245
- def initialize(criteria)
246
- @criteria = criteria
247
- if klass.hereditary? && !criteria.selector.keys.include?(:_type)
248
- @criteria = criteria.in(:_type => criteria.klass._types)
249
- end
250
- @criteria.cache if klass.cached?
251
- end
252
-
253
- # Iterate over each +Document+ in the results. This can take an optional
254
- # block to pass to each argument in the results.
255
- #
256
- # @example Iterate over the results.
257
- # context.iterate { |doc| p doc }
258
- def iterate(&block)
259
- selecting do
260
- return caching(&block) if cached?
261
- if block_given?
262
- execute.each { |doc| yield doc }
263
- end
264
- end
265
- end
266
-
267
- # Return the last result for the +Context+. Essentially does a find_one on
268
- # the collection with the sorting reversed. If no sorting parameters have
269
- # been provided it will default to ids.
270
- #
271
- # @example Get the last document.
272
- # context.last
273
- #
274
- # @return [ Document ] The last document in the collection.
275
- def last
276
- opts = options_with_default_sorting
277
- opts[:sort] = opts[:sort].map{ |option| [ option[0], option[1].invert ] }.uniq
278
- attributes = klass.collection.find_one(selector, opts)
279
- return nil unless attributes
280
- selecting do
281
- Mongoid::Factory.from_db(klass, attributes).tap do |doc|
282
- eager_load([ doc ]) if criteria.inclusions.any?
283
- end
284
- end
285
- end
286
-
287
- # Return the max value for a field.
288
- #
289
- # This will take the internally built selector and options
290
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
291
- # collection itself will be retrieved from the class provided, and once the
292
- # query has returned it will provided a grouping of keys with sums.
293
- #
294
- # @example Get the max value.
295
- # context.max(:age)
296
- #
297
- # @param [ Symbol ] field The field to get the max for.
298
- #
299
- # @return [ Numeric ] A numeric max value.
300
- def max(field)
301
- grouped(:max, field.to_s, Javascript.max, Javascript.max_finalize)
302
- end
303
-
304
- # Return the min value for a field.
305
- #
306
- # This will take the internally built selector and options
307
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
308
- # collection itself will be retrieved from the class provided, and once the
309
- # query has returned it will provided a grouping of keys with sums.
310
- #
311
- # @example Get the min value.
312
- # context.min(:age)
313
- #
314
- # @param [ Symbol ] field The field to get the min for.
315
- #
316
- # @return [ Numeric ] A numeric minimum value.
317
- def min(field)
318
- grouped(:min, field.to_s, Javascript.min, Javascript.min_finalize)
319
- end
320
-
321
- # Perform a pull on the matching documents.
322
- #
323
- # @example Pull on all matching.
324
- # Person.where(:name => "Alex").pull(:aliases, "value")
325
- #
326
- # @param [ String ] field The field to pull from.
327
- # @param [ Object ] value The value to pull.
328
- #
329
- # @return [ Object ] The update value.
330
- #
331
- # @since 2.1.0
332
- def pull(field, value)
333
- klass.collection.update(
334
- selector,
335
- { "$pull" => { field => value } },
336
- :multi => true
337
- )
338
- end
339
-
340
- # Return the first result for the +Context+ and skip it
341
- # for successive calls.
342
- #
343
- # @example Get the first document and shift.
344
- # context.shift
345
- #
346
- # @return [ Document ] The first document in the collection.
347
- def shift
348
- first.tap { criteria.skip((options[:skip] || 0) + 1) }
349
- end
350
-
351
- # Sum the context.
352
- #
353
- # This will take the internally built selector and options
354
- # and pass them on to the Ruby driver's +group()+ method on the collection. The
355
- # collection itself will be retrieved from the class provided, and once the
356
- # query has returned it will provided a grouping of keys with sums.
357
- #
358
- # @example Get the sum for a field.
359
- # context.sum(:age)
360
- #
361
- # @param [ Symbol ] field The field who's values to sum.
362
- #
363
- # @return [ Numeric ] A numeric value that is the sum.
364
- def sum(field)
365
- grouped(:sum, field.to_s, Javascript.sum, Javascript.sum_finalize)
366
- end
367
-
368
- # Very basic update that will perform a simple atomic $set of the
369
- # attributes provided in the hash. Can be expanded to later for more
370
- # robust functionality.
371
- #
372
- # @example Update all matching documents.
373
- # context.update_all(:title => "Sir")
374
- #
375
- # @param [ Hash ] attributes The sets to perform.
376
- #
377
- # @since 2.0.0.rc.4
378
- def update_all(attributes = {})
379
- klass.collection.update(
380
- selector,
381
- { "$set" => attributes },
382
- Safety.merge_safety_options(:multi => true)
383
- ).tap do
384
- Threaded.clear_options!
385
- end
386
- end
387
- alias :update :update_all
388
-
389
- protected
390
-
391
- # Iterate over each +Document+ in the results and cache the collection.
392
- #
393
- # @example Execute with caching.
394
- # context.caching
395
- def caching(&block)
396
- if defined? @collection
397
- @collection.each(&block)
398
- else
399
- @collection = []
400
- execute.each do |doc|
401
- @collection << doc
402
- yield doc if block_given?
403
- end
404
- end
405
- end
406
-
407
- # Common functionality for grouping operations. Currently used by min, max
408
- # and sum. Will gsub the field name in the supplied reduce function.
409
- #
410
- # @example Execute the group function.
411
- # context.group(0, :avg, "")
412
- #
413
- # @param [ Object ] start The value to start the map/reduce with.
414
- # @param [ String ] field The field to aggregate.
415
- # @param [ String ] reduce The reduce JS function.
416
- #
417
- # @return [ Numeric ] A numeric result.
418
- def grouped(start, field, reduce, finalize)
419
- collection = klass.collection.group(
420
- :cond => selector,
421
- :initial => { start => "start" },
422
- :finalize => finalize,
423
- :reduce => reduce.gsub("[field]", field)
424
- )
425
- collection.empty? ? nil : collection.first[start.to_s]
426
- end
427
-
428
- # Get the options hash with the default sorting options provided.
429
- #
430
- # @example Get the options.
431
- # criteria.options_with_default_sorting
432
- #
433
- # @return [ Hash ] The options.
434
- #
435
- # @since 2.3.2
436
- def options_with_default_sorting
437
- process_options.tap do |opts|
438
- if opts[:sort].blank?
439
- opts[:sort] = [[ :_id, :asc ]]
440
- end
441
- end
442
- end
443
-
444
- # Filters the field list. If no fields have been supplied, then it will be
445
- # empty. If fields have been defined then _type will be included as well.
446
- #
447
- # @example Process the field list.
448
- # context.process_options
449
- #
450
- # @return [ Hash ] The options.
451
- def process_options
452
- fields = options[:fields]
453
- if fields && fields.size > 0 && !fields.include?(:_type)
454
- if fields.kind_of?(Hash)
455
- fields[:_type] = 1 if fields.first.last != 0 # Not excluding
456
- else
457
- fields << :type
458
- end
459
- options[:fields] = fields
460
- end
461
- options.dup
462
- end
463
-
464
- # If we are limiting results, we need to set the field limitations on a
465
- # thread local to avoid overriding the default values.
466
- #
467
- # @example Execute with selection.
468
- # context.selecting do
469
- # collection.find
470
- # end
471
- #
472
- # @return [ Object ] The yielded value.
473
- #
474
- # @since 2.4.4
475
- def selecting
476
- begin
477
- unless options[:fields].blank?
478
- Threaded.selection = options[:fields]
479
- end
480
- yield
481
- ensure
482
- Threaded.selection = nil
483
- end
484
- end
485
- end
486
- end
487
- end