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
@@ -1,108 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Criterion #:nodoc:
4
-
5
- # This module contains criteria behaviour for exclusion of values.
6
- module Exclusion
7
-
8
- # Adds a criterion to the +Criteria+ that specifies values that are not
9
- # allowed to match any document in the database. The MongoDB
10
- # conditional operator that will be used is "$ne".
11
- #
12
- # @example Match documents without these values.
13
- # criteria.excludes(:field => "value1")
14
- # criteria.excludes(:field1 => "value1", :field2 => "value1")
15
- #
16
- # @param [ Hash ] attributes: A +Hash+ where the key is the field
17
- # name and the value is a value that must not be equal to the
18
- # corresponding field value in the database.
19
- #
20
- # @return [ Criteria ] A newly cloned copy.
21
- def excludes(attributes = {})
22
- mongo_id = attributes.delete(:id)
23
- attributes = attributes.merge(:_id => mongo_id) if mongo_id
24
- update_selector(attributes, "$ne")
25
- end
26
-
27
- # Used when wanting to set the fields options directly using a hash
28
- # instead of going through only or without.
29
- #
30
- # @example Set the limited fields.
31
- # criteria.fields(:field => 1)
32
- #
33
- # @param [ Hash ] attributes The field options.
34
- #
35
- # @return [ Criteria ] A newly cloned copy.
36
- #
37
- # @since 2.0.2
38
- def fields(attributes = nil)
39
- clone.tap { |crit| crit.options[:fields] = attributes || {} }
40
- end
41
-
42
- # Adds a criterion to the +Criteria+ that specifies values where none
43
- # should match in order to return results. This is similar to an SQL
44
- # "NOT IN" clause. The MongoDB conditional operator that will be
45
- # used is "$nin".
46
- #
47
- # @example Match documents with values not in the provided.
48
- # criteria.not_in(:field => ["value1", "value2"])
49
- # criteria.not_in(:field1 => ["value1", "value2"], :field2 => ["value1"])
50
- #
51
- # @param [ Hash ] attributes A +Hash+ where the key is the field name
52
- # and the value is an +Array+ of values that none can match.
53
- #
54
- # @return [ Criteria ] A newly cloned copy.
55
- def not_in(attributes)
56
- update_selector(attributes, "$nin")
57
- end
58
-
59
- # Adds a criterion to the +Criteria+ that specifies the fields that will
60
- # get returned from the Document. Used mainly for list views that do not
61
- # require all fields to be present. This is similar to SQL "SELECT" values.
62
- #
63
- # @example Limit the fields to only the specified.
64
- # criteria.only(:field1, :field2, :field3)
65
- #
66
- # @note #only and #without cannot be used together.
67
- #
68
- # @param [ Array<Symbol> ] args A list of field names to limit to.
69
- #
70
- # @return [ Criteria ] A newly cloned copy.
71
- def only(*args)
72
- clone.tap do |crit|
73
- if args.any?
74
- crit.options[:fields] = {:_type => 1}
75
- crit.field_list = args.flatten
76
- crit.field_list.each do |f|
77
- crit.options[:fields][f] = 1
78
- end
79
- end
80
- end
81
- end
82
-
83
- # Adds a criterion to the +Criteria+ that specifies the fields that will
84
- # not get returned by the document.
85
- #
86
- # @example Filter out specific fields.
87
- # criteria.without(:field2, :field2)
88
- #
89
- # @note #only and #without cannot be used together.
90
- #
91
- # @param [ Array<Symbol> args A list of fields to exclude.
92
- #
93
- # @return [ Criteria ] A newly cloned copy.
94
- #
95
- # @since 2.0.0
96
- def without(*args)
97
- clone.tap do |crit|
98
- if args.any?
99
- crit.options[:fields] = {}
100
- args.flatten.each do |f|
101
- crit.options[:fields][f] = 0
102
- end
103
- end
104
- end
105
- end
106
- end
107
- end
108
- end
@@ -1,290 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Criterion #:nodoc:
4
- module Inclusion
5
-
6
- # Adds a criterion to the +Criteria+ that specifies values that must all
7
- # be matched in order to return results. Similar to an "in" clause but the
8
- # underlying conditional logic is an "AND" and not an "OR". The MongoDB
9
- # conditional operator that will be used is "$all".
10
- #
11
- # @example Adding the criterion.
12
- # criteria.all(:field => ["value1", "value2"])
13
- # criteria.all(:field1 => ["value1", "value2"], :field2 => ["value1"])
14
- #
15
- # @param [ Hash ] attributes Name/value pairs that all must match.
16
- #
17
- # @return [ Criteria ] A new criteria with the added selector.
18
- def all(attributes = {})
19
- update_selector(attributes, "$all")
20
- end
21
- alias :all_in :all
22
-
23
- # Adds a criterion to the criteria that specifies multiple expressions
24
- # that *all* must match. This uses MongoDB's $and operator under the
25
- # covers.
26
- #
27
- # @example Match all provided expressions.
28
- # criteria.all_of(:name => value, :age.gt => 18)
29
- #
30
- # @param [ Array<Hash> ] Multiple hash expressions.
31
- #
32
- # @return [ Criteria ] The criteria object.
33
- #
34
- # @since 2.3.0
35
- def all_of(*args)
36
- clone.tap do |crit|
37
- unless args.empty?
38
- criterion = @selector["$and"] || []
39
- converted = BSON::ObjectId.convert(klass, args.flatten)
40
- expanded = converted.collect { |hash| hash.expand_complex_criteria }
41
- crit.selector["$and"] = criterion.concat(expanded)
42
- end
43
- end
44
- end
45
-
46
- # Adds a criterion to the +Criteria+ that specifies values where any can
47
- # be matched in order to return results. This is similar to an SQL "IN"
48
- # clause. The MongoDB conditional operator that will be used is "$in".
49
- # Any previously matching "$in" arrays will be unioned with new
50
- # arguments.
51
- #
52
- # @example Adding the criterion.
53
- # criteria.in(:field => ["value1"]).also_in(:field => ["value2"])
54
- #
55
- # @param [ Hash ] attributes Name/value pairs any can match.
56
- #
57
- # @return [ Criteria ] A new criteria with the added selector.
58
- def also_in(attributes = {})
59
- update_selector(attributes, "$in")
60
- end
61
-
62
- # Adds a criterion to the +Criteria+ that specifies values that must
63
- # be matched in order to return results. This is similar to a SQL "WHERE"
64
- # clause. This is the actual selector that will be provided to MongoDB,
65
- # similar to the Javascript object that is used when performing a find()
66
- # in the MongoDB console.
67
- #
68
- # @example Adding the criterion.
69
- # criteria.and(:field1 => "value1", :field2 => 15)
70
- #
71
- # @param [ Hash ] selectior Name/value pairs that all must match.
72
- #
73
- # @return [ Criteria ] A new criteria with the added selector.
74
- def and(selector = nil)
75
- where(selector)
76
- end
77
-
78
- # Adds a criterion to the +Criteria+ that specifies a set of expressions
79
- # to match if any of them return true. This is a $or query in MongoDB and
80
- # is similar to a SQL OR. This is named #any_of and aliased "or" for
81
- # readability.
82
- #
83
- # @example Adding the criterion.
84
- # criteria.any_of({ :field1 => "value" }, { :field2 => "value2" })
85
- #
86
- # @param [ Array<Hash> ] args A list of name/value pairs any can match.
87
- #
88
- # @return [ Criteria ] A new criteria with the added selector.
89
- def any_of(*args)
90
- clone.tap do |crit|
91
- criterion = @selector["$or"] || []
92
- converted = BSON::ObjectId.convert(klass, args.flatten)
93
- expanded = converted.collect { |hash| hash.expand_complex_criteria }
94
- crit.selector["$or"] = criterion.concat(expanded)
95
- end
96
- end
97
- alias :or :any_of
98
-
99
- # Find the matchind document in the criteria, either based on id or
100
- # conditions.
101
- #
102
- # @todo Durran: DRY up duplicated code in a few places.
103
- #
104
- # @example Find by an id.
105
- # criteria.find(BSON::ObjectId.new)
106
- #
107
- # @example Find by multiple ids.
108
- # criteria.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
109
- #
110
- # @example Conditionally find all matching documents.
111
- # criteria.find(:all, :conditions => { :title => "Sir" })
112
- #
113
- # @example Conditionally find the first document.
114
- # criteria.find(:first, :conditions => { :title => "Sir" })
115
- #
116
- # @example Conditionally find the last document.
117
- # criteria.find(:last, :conditions => { :title => "Sir" })
118
- #
119
- # @param [ Symbol, BSON::ObjectId, Array<BSON::ObjectId> ] arg The
120
- # argument to search with.
121
- # @param [ Hash ] options The options to search with.
122
- #
123
- # @return [ Document, Criteria ] The matching document(s).
124
- def find(*args)
125
- type, crit = search(*args)
126
- case type
127
- when :first then crit.one
128
- when :last then crit.last
129
- when :ids then crit.execute_or_raise(args)
130
- else
131
- crit
132
- end
133
- end
134
-
135
- # Execute the criteria or raise an error if no documents found.
136
- #
137
- # @example Execute or raise
138
- # criteria.execute_or_raise(id, criteria)
139
- #
140
- # @param [ Object ] args The arguments passed.
141
- # @param [ Criteria ] criteria The criteria to execute.
142
- #
143
- # @raise [ Errors::DocumentNotFound ] If nothing returned.
144
- #
145
- # @return [ Document, Array<Document> ] The document(s).
146
- #
147
- # @since 2.0.0
148
- def execute_or_raise(args)
149
- (args[0].is_a?(Array) ? entries : from_map_or_db).tap do |result|
150
- if Mongoid.raise_not_found_error && !args.flatten.blank?
151
- raise Errors::DocumentNotFound.new(klass, args) if result._vacant?
152
- end
153
- end
154
- end
155
-
156
- # Get the document from the identity map, and if not found hit the
157
- # database.
158
- #
159
- # @example Get the document from the map or criteria.
160
- # criteria.from_map_or_db(criteria)
161
- #
162
- # @param [ Criteria ] The cloned criteria.
163
- #
164
- # @return [ Document ] The found document.
165
- #
166
- # @since 2.2.1
167
- def from_map_or_db
168
- doc = IdentityMap.get(klass, extract_id || selector)
169
- doc && doc.matches?(selector) ? doc : first
170
- end
171
-
172
- # Adds a criterion to the +Criteria+ that specifies values where any can
173
- # be matched in order to return results. This is similar to an SQL "IN"
174
- # clause. The MongoDB conditional operator that will be used is "$in".
175
- #
176
- # @example Adding the criterion.
177
- # criteria.in(:field => ["value1", "value2"])
178
- # criteria.in(:field1 => ["value1", "value2"], :field2 => ["value1"])
179
- #
180
- # @param [ Hash ] attributes Name/value pairs any can match.
181
- #
182
- # @return [ Criteria ] A new criteria with the added selector.
183
- def in(attributes = {})
184
- update_selector(attributes, "$in", :&)
185
- end
186
- alias :any_in :in
187
-
188
- # Eager loads all the provided relations. Will load all the documents
189
- # into the identity map who's ids match based on the extra query for the
190
- # ids.
191
- #
192
- # @note This will only work if Mongoid's identity map is enabled. To do
193
- # so set identity_map_enabled: true in your mongoid.yml
194
- #
195
- # @note This will work for embedded relations that reference another
196
- # collection via belongs_to as well.
197
- #
198
- # @note Eager loading brings all the documents into memory, so there is a
199
- # sweet spot on the performance gains. Internal benchmarks show that
200
- # eager loading becomes slower around 100k documents, but this will
201
- # naturally depend on the specific application.
202
- #
203
- # @example Eager load the provided relations.
204
- # Person.includes(:posts, :game)
205
- #
206
- # @param [ Array<Symbol> ] relations The names of the relations to eager
207
- # load.
208
- #
209
- # @return [ Criteria ] The cloned criteria.
210
- #
211
- # @since 2.2.0
212
- def includes(*relations)
213
- relations.flatten.each do |name|
214
- inclusions.push(klass.reflect_on_association(name))
215
- end
216
- clone
217
- end
218
-
219
- # Get a list of criteria that are to be executed for eager loading.
220
- #
221
- # @example Get the eager loading inclusions.
222
- # Person.includes(:game).inclusions
223
- #
224
- # @return [ Array<Metadata> ] The inclusions.
225
- #
226
- # @since 2.2.0
227
- def inclusions
228
- @inclusions ||= []
229
- end
230
-
231
- # Adds a criterion to the +Criteria+ that specifies values to do
232
- # geospacial searches by. The field must be indexed with the "2d" option.
233
- #
234
- # @example Adding the criterion.
235
- # criteria.near(:field1 => [30, -44])
236
- #
237
- # @param [ Hash ] attributes The fields with lat/long values.
238
- #
239
- # @return [ Criteria ] A new criteria with the added selector.
240
- def near(attributes = {})
241
- update_selector(attributes, "$near")
242
- end
243
-
244
- # Adds a criterion to the +Criteria+ that specifies values that must
245
- # be matched in order to return results. This is similar to a SQL "WHERE"
246
- # clause. This is the actual selector that will be provided to MongoDB,
247
- # similar to the Javascript object that is used when performing a find()
248
- # in the MongoDB console.
249
- #
250
- # @example Adding the criterion.
251
- # criteria.where(:field1 => "value1", :field2 => 15)
252
- #
253
- # @param [ Hash ] selector Name/value pairs where all must match.
254
- #
255
- # @return [ Criteria ] A new criteria with the added selector.
256
- def where(selector = nil)
257
- clone.tap do |crit|
258
- selector = case selector
259
- when String then {"$where" => selector}
260
- else
261
- BSON::ObjectId.convert(klass, selector || {}, false).expand_complex_criteria
262
- end
263
-
264
- # @todo: Durran: 3.0.0: refactor the merging into separate strategies
265
- # to clean this funkiness up.
266
- selector.each_pair do |key, value|
267
- if crit.selector.has_key?(key)
268
- if key.mongoid_id?
269
- if crit.selector.has_key?("$and")
270
- crit.selector["$and"] << { key => value }
271
- elsif crit.selector[key] != value
272
- crit.selector["$and"] = [{ key => crit.selector.delete(key) }, { key => value }]
273
- end
274
- elsif crit.selector[key].respond_to?(:merge) && value.respond_to?(:merge)
275
- crit.selector[key] =
276
- crit.selector[key].merge(value) do |key, old, new|
277
- key == '$in' ? old & new : new
278
- end
279
- else
280
- crit.selector[key] = value
281
- end
282
- else
283
- crit.selector[key] = value
284
- end
285
- end
286
- end
287
- end
288
- end
289
- end
290
- end
@@ -1,259 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Criterion #:nodoc:
4
- module Optional
5
-
6
- # Adds fields to be sorted in ascending order. Will add them in the order
7
- # they were passed into the method.
8
- #
9
- # @example Sort in ascending order.
10
- # criteria.ascending(:title, :dob)
11
- # criteria.asc(:title, :dob)
12
- #
13
- # @param [ Array<Symbol> ] fields The fields to sort on.
14
- #
15
- # @return [ Criteria ] The cloned criteria.
16
- def ascending(*fields)
17
- clone.tap do |crit|
18
- setup_sort_options(crit.options) unless fields.first.nil?
19
- fields.flatten.each { |field| merge_options(crit.options[:sort], [ localize(field), :asc ]) }
20
- end
21
- end
22
- alias :asc :ascending
23
-
24
- # Tells the criteria that the cursor that gets returned needs to be
25
- # cached. This is so multiple iterations don't hit the database multiple
26
- # times, however this is not advisable when working with large data sets
27
- # as the entire results will get stored in memory.
28
- #
29
- # @example Flag the criteria as cached.
30
- # criteria.cache
31
- #
32
- # @return [ Criteria ] The cloned criteria.
33
- def cache
34
- clone.tap { |crit| crit.options.merge!(:cache => true) }
35
- end
36
-
37
- # Will return true if the cache option has been set.
38
- #
39
- # @example Is the criteria cached?
40
- # criteria.cached?
41
- #
42
- # @return [ true, false ] If the criteria is flagged as cached.
43
- def cached?
44
- options[:cache] == true
45
- end
46
-
47
- # Adds fields to be sorted in descending order. Will add them in the order
48
- # they were passed into the method.
49
- #
50
- # @example Sort the criteria in descending order.
51
- # criteria.descending(:title, :dob)
52
- # criteria.desc(:title, :dob)
53
- #
54
- # @param [ Array<Symbol> ] fields The fields to sort on.
55
- #
56
- # @return [ Criteria ] The cloned criteria.
57
- def descending(*fields)
58
- clone.tap do |crit|
59
- setup_sort_options(crit.options) unless fields.first.nil?
60
- fields.flatten.each { |field| merge_options(crit.options[:sort], [ localize(field), :desc ]) }
61
- end
62
- end
63
- alias :desc :descending
64
-
65
- # Adds a criterion to the +Criteria+ that specifies additional options
66
- # to be passed to the Ruby driver, in the exact format for the driver.
67
- #
68
- # @example Add extra params to the criteria.
69
- # criteria.extras(:limit => 20, :skip => 40)
70
- #
71
- # @param [ Hash ] extras The extra driver options.
72
- #
73
- # @return [ Criteria ] The cloned criteria.
74
- def extras(extras)
75
- clone.tap do |crit|
76
- crit.options.merge!(extras)
77
- end
78
- end
79
-
80
- # Adds a criterion to the +Criteria+ that specifies an id that must be matched.
81
- #
82
- # @example Add a single id criteria.
83
- # criteria.for_ids("4ab2bc4b8ad548971900005c")
84
- #
85
- # @example Add multiple id criteria.
86
- # criteria.for_ids(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"])
87
- #
88
- # @param [ Array ] ids: A single id or an array of ids.
89
- #
90
- # @return [ Criteria ] The cloned criteria.
91
- def for_ids(*ids)
92
- field = klass.fields["_id"]
93
- ids.flatten!
94
- if ids.size > 1
95
- any_in(:_id => ids.map{ |id| field.serialize(id) })
96
- else
97
- where(:_id => field.serialize(ids.first))
98
- end
99
- end
100
-
101
- # Adds a criterion to the +Criteria+ that specifies the maximum number of
102
- # results to return. This is mostly used in conjunction with skip()
103
- # to handle paginated results.
104
- #
105
- # @example Limit the result set size.
106
- # criteria.limit(100)
107
- #
108
- # @param [ Integer ] value The max number of results.
109
- #
110
- # @return [ Criteria ] The cloned criteria.
111
- def limit(value = 20)
112
- clone.tap { |crit| crit.options[:limit] = value.to_i }
113
- end
114
-
115
- # Returns the offset option. If a per_page option is in the list then it
116
- # will replace it with a skip parameter and return the same value. Defaults
117
- # to 20 if nothing was provided.
118
- #
119
- # @example Get the offset.
120
- # criteria.offset(10)
121
- #
122
- # @return [ Integer ] The number of documents to skip.
123
- def offset(*args)
124
- args.size > 0 ? skip(args.first) : options[:skip]
125
- end
126
-
127
- # Adds a criterion to the +Criteria+ that specifies the sort order of
128
- # the returned documents in the database. Similar to a SQL "ORDER BY".
129
- #
130
- # @example Order by specific fields.
131
- # criteria.order_by([[:field1, :asc], [:field2, :desc]])
132
- #
133
- # @param [ Array ] params: An +Array+ of [field, direction] sorting pairs.
134
- #
135
- # @return [ Criteria ] The cloned criteria.
136
- def order_by(*args)
137
- clone.tap do |crit|
138
- arguments = args.size == 1 ? args.first : args
139
- setup_sort_options(crit.options) unless args.first.nil?
140
- if arguments.is_a?(Array)
141
- #[:name, :asc]
142
- if arguments.size == 2 && (arguments.first.is_a?(Symbol) || arguments.first.is_a?(String))
143
- build_order_options(arguments, crit)
144
- else
145
- arguments.each { |argument| build_order_options(argument, crit) }
146
- end
147
- else
148
- build_order_options(arguments, crit)
149
- end
150
- end
151
- end
152
- alias :order :order_by
153
-
154
- # Adds a criterion to the +Criteria+ that specifies how many results to skip
155
- # when returning Documents. This is mostly used in conjunction with
156
- # limit() to handle paginated results, and is similar to the
157
- # traditional "offset" parameter.
158
- #
159
- # @example Skip a specified number of documents.
160
- # criteria.skip(20)
161
- #
162
- # @param [ Integer ] value The number of results to skip.
163
- #
164
- # @return [ Criteria ] The cloned criteria.
165
- def skip(value = 0)
166
- clone.tap { |crit| crit.options[:skip] = value.to_i }
167
- end
168
-
169
- # Adds a criterion to the +Criteria+ that specifies a type or an Array of
170
- # types that must be matched.
171
- #
172
- # @example Match only specific models.
173
- # criteria.type('Browser')
174
- # criteria.type(['Firefox', 'Browser'])
175
- #
176
- # @param [ Array<String> ] types The types to match against.
177
- #
178
- # @return [ Criteria ] The cloned criteria.
179
- def type(types)
180
- types = [types] unless types.is_a?(Array)
181
- any_in(:_type => types)
182
- end
183
-
184
- private
185
-
186
- # Build ordering options from given arguments on given criteria
187
- #
188
- # @example build order options
189
- # criteria.build_order_options(:name.asc, criteria)
190
- #
191
- #
192
- # @param [ <Hash>, <Array>, <Complex> ] argument to build criteria from
193
- # @param [ Criterion ] criterion to change
194
- def build_order_options(arguments, crit)
195
- case arguments
196
- when Hash
197
- if arguments.size > 1
198
- raise ArgumentError, "Please don't use hash to define multiple orders " +
199
- "due to the fact that hash doesn't have order this may cause unpredictable results"
200
- end
201
- arguments.each_pair do |field, direction|
202
- merge_options(crit.options[:sort], [ localize(field), direction ])
203
- end
204
- when Array
205
- merge_options(crit.options[:sort], arguments.map{ |field| localize(field) })
206
- when Complex
207
- merge_options(crit.options[:sort], [ localize(arguments.key), arguments.operator.to_sym ])
208
- end
209
- end
210
-
211
- # Merge options for order_by criterion
212
- # Allow only one order direction for same field
213
- #
214
- # @example Merge ordering options
215
- # criteria.merge_options([[:title, :asc], [:created_at, :asc]], [:title, :desc])
216
- #
217
- #
218
- # @param [ Array<Array> ] Existing options
219
- # @param [ Array ] New option for merge.
220
- #
221
- # @since 2.1.0
222
- def merge_options(options, new_option)
223
- old_option = options.assoc(new_option.first)
224
-
225
- if old_option
226
- options[options.index(old_option)] = new_option.flatten
227
- else
228
- options << new_option.flatten
229
- end
230
- end
231
-
232
- # Initialize the sort options
233
- # Set options[:sort] to an empty array if it does not exist, or dup it if
234
- # it already has been defined
235
- #
236
- # @example criteria.setup_sort_options(crit.options)
237
- #
238
- # @param [ Array<Array> ] Existing options
239
- #
240
- # @since 2.4.0
241
- def setup_sort_options(options)
242
- options[:sort] = options[:sort] ? options[:sort].dup : []
243
- end
244
-
245
- # Check if field is localized and return localized version if it is.
246
- #
247
- # @example localize
248
- # criteria.localize(:description)
249
- #
250
- # @param [ <Symbol> ] field to localize
251
- def localize(field)
252
- if klass.fields[field.to_s].try(:localized?)
253
- field = "#{field}.#{::I18n.locale}".to_sym
254
- end
255
- field
256
- end
257
- end
258
- end
259
- end