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,329 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+
4
+ # This module contains behaviour for all Mongoid scoping - named scopes,
5
+ # default scopes, and criteria accessors via scoped and unscoped.
6
+ module Scoping
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ class_attribute :default_scoping
11
+ class_attribute :scopes
12
+ self.scopes = {}
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ # Add a default scope to the model. This scope will be applied to all
18
+ # criteria unless #unscoped is specified.
19
+ #
20
+ # @example Define a default scope with a criteria.
21
+ # class Band
22
+ # include Mongoid::Document
23
+ # field :active, type: Boolean
24
+ # default_scope where(active: true)
25
+ # end
26
+ #
27
+ # @example Define a default scope with a proc.
28
+ # class Band
29
+ # include Mongoid::Document
30
+ # field :active, type: Boolean
31
+ # default_scope ->{ where(active: true) }
32
+ # end
33
+ #
34
+ # @param [ Proc, Criteria ] scope The default scope.
35
+ #
36
+ # @raise [ Errors::InvalidScope ] If the scope is not a proc or criteria.
37
+ #
38
+ # @return [ Proc ] The default scope.
39
+ #
40
+ # @since 1.0.0
41
+ def default_scope(value)
42
+ check_scope_validity(value)
43
+ self.default_scoping = value.to_proc
44
+ end
45
+
46
+ # Is the class able to have the default scope applied?
47
+ #
48
+ # @example Can the default scope be applied?
49
+ # Band.default_scopable?
50
+ #
51
+ # @return [ true, false ] If the default scope can be applied.
52
+ #
53
+ # @since 3.0.0
54
+ def default_scopable?
55
+ default_scoping? && !Threaded.executing?(:without_default_scope)
56
+ end
57
+
58
+ # Get a queryable, either the last one on the scope stack or a fresh one.
59
+ #
60
+ # @api private
61
+ #
62
+ # @example Get a queryable.
63
+ # Model.queryable
64
+ #
65
+ # @return [ Criteria ] The queryable.
66
+ #
67
+ # @since 3.0.0
68
+ def queryable
69
+ scope_stack.last || Criteria.new(self)
70
+ end
71
+
72
+ # Create a scope that can be accessed from the class level or chained to
73
+ # criteria by the provided name.
74
+ #
75
+ # @example Create named scopes.
76
+ #
77
+ # class Person
78
+ # include Mongoid::Document
79
+ # field :active, type: Boolean
80
+ # field :count, type: Integer
81
+ #
82
+ # scope :active, where(active: true)
83
+ # scope :at_least, ->(count){ where(:count.gt => count) }
84
+ # end
85
+ #
86
+ # @param [ Symbol ] name The name of the scope.
87
+ # @param [ Proc, Criteria ] conditions The conditions of the scope.
88
+ #
89
+ # @raise [ Errors::InvalidScope ] If the scope is not a proc or criteria.
90
+ # @raise [ Errors::ScopeOverwrite ] If the scope name already exists.
91
+ #
92
+ # @since 1.0.0
93
+ def scope(name, value, &block)
94
+ normalized = name.to_sym
95
+ check_scope_validity(value)
96
+ check_scope_name(normalized)
97
+ scopes[normalized] = {
98
+ scope: strip_default_scope(value),
99
+ extension: Module.new(&block)
100
+ }
101
+ define_scope_method(normalized)
102
+ end
103
+
104
+ # Initializes and returns the current scope stack.
105
+ #
106
+ # @example Get the scope stack.
107
+ # Person.scope_stack
108
+ #
109
+ # @return [ Array<Criteria> ] The scope stack.
110
+ #
111
+ # @since 1.0.0
112
+ def scope_stack
113
+ Threaded.scope_stack[object_id] ||= []
114
+ end
115
+
116
+ # Get a criteria for the document with normal scoping.
117
+ #
118
+ # @example Get the criteria.
119
+ # Band.scoped(skip: 10)
120
+ #
121
+ # @note This will force the default scope to be applied.
122
+ #
123
+ # @param [ Hash ] options Query options for the criteria.
124
+ #
125
+ # @option options [ Integer ] :skip Optional number of documents to skip.
126
+ # @option options [ Integer ] :limit Optional number of documents to
127
+ # limit.
128
+ # @option options [ Array ] :sort Optional sorting options.
129
+ #
130
+ # @return [ Criteria ] A scoped criteria.
131
+ #
132
+ # @since 3.0.0
133
+ def scoped(options = nil)
134
+ queryable.scoped(options)
135
+ end
136
+
137
+ # Get the criteria without the default scoping applied.
138
+ #
139
+ # @example Get the unscoped criteria.
140
+ # Band.unscoped
141
+ #
142
+ # @example Yield to block with no default scoping.
143
+ # Band.unscoped do
144
+ # Band.where(name: "Depeche Mode")
145
+ # end
146
+ #
147
+ # @note This will force the default scope to be removed.
148
+ #
149
+ # @return [ Criteria, Object ] The unscoped criteria or result of the
150
+ # block.
151
+ #
152
+ # @since 3.0.0
153
+ def unscoped
154
+ if block_given?
155
+ without_default_scope do
156
+ yield(self)
157
+ end
158
+ else
159
+ queryable.unscoped
160
+ end
161
+ end
162
+
163
+ # Get a criteria with the default scope applied, if possible.
164
+ #
165
+ # @example Get a criteria with the default scope.
166
+ # Model.with_default_scope
167
+ #
168
+ # @return [ Criteria ] The criteria.
169
+ #
170
+ # @since 3.0.0
171
+ def with_default_scope
172
+ queryable.with_default_scope
173
+ end
174
+ alias :criteria :with_default_scope
175
+
176
+ # Pushes the provided criteria onto the scope stack, and removes it after the
177
+ # provided block is yielded.
178
+ #
179
+ # @example Yield to the criteria.
180
+ # Person.with_scope(criteria)
181
+ #
182
+ # @param [ Criteria ] criteria The criteria to apply.
183
+ #
184
+ # @return [ Criteria ] The yielded criteria.
185
+ #
186
+ # @since 1.0.0
187
+ def with_scope(criteria)
188
+ scope_stack.push(criteria)
189
+ begin
190
+ yield criteria
191
+ ensure
192
+ scope_stack.pop
193
+ end
194
+ end
195
+
196
+ # Execute the block without applying the default scope.
197
+ #
198
+ # @example Execute without the default scope.
199
+ # Band.without_default_scope do
200
+ # Band.where(name: "Depeche Mode")
201
+ # end
202
+ #
203
+ # @return [ Object ] The result of the block.
204
+ #
205
+ # @since 3.0.0
206
+ def without_default_scope
207
+ Threaded.begin("without_default_scope")
208
+ yield
209
+ ensure
210
+ Threaded.exit("without_default_scope")
211
+ end
212
+
213
+ private
214
+
215
+ # Warns or raises exception if overriding another scope or method.
216
+ #
217
+ # @api private
218
+ #
219
+ # @example Warn or raise error if name exists.
220
+ # Model.valid_scope_name?("test")
221
+ #
222
+ # @param [ String, Symbol ] name The name of the scope.
223
+ #
224
+ # @raise [ Errors::ScopeOverwrite ] If the name exists and configured to
225
+ # raise the error.
226
+ #
227
+ # @since 2.1.0
228
+ def check_scope_name(name)
229
+ if scopes[name] || respond_to?(name, true)
230
+ if Mongoid.scope_overwrite_exception
231
+ raise Errors::ScopeOverwrite.new(self.name, name)
232
+ else
233
+ if Mongoid.logger
234
+ Mongoid.logger.warn(
235
+ "Creating scope :#{name}. " +
236
+ "Overwriting existing method #{self.name}.#{name}."
237
+ )
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ # Checks if the intended scope is a valid object, either a criteria or
244
+ # proc with a criteria.
245
+ #
246
+ # @api private
247
+ #
248
+ # @example Check if the scope is valid.
249
+ # Model.check_scope_validity({})
250
+ #
251
+ # @param [ Object ] value The intended scope.
252
+ #
253
+ # @raise [ Errors::InvalidScope ] If the scope is not a valid object.
254
+ #
255
+ # @since 3.0.0
256
+ def check_scope_validity(value)
257
+ unless value.respond_to?(:to_proc)
258
+ raise Errors::InvalidScope.new(self, value)
259
+ end
260
+ end
261
+
262
+ # Defines the actual class method that will execute the scope when
263
+ # called.
264
+ #
265
+ # @api private
266
+ #
267
+ # @example Define the scope class method.
268
+ # Model.define_scope_method(:active)
269
+ #
270
+ # @param [ Symbol ] name The method/scope name.
271
+ #
272
+ # @return [ Method ] The defined method.
273
+ #
274
+ # @since 3.0.0
275
+ def define_scope_method(name)
276
+ (class << self; self; end).class_eval <<-SCOPE
277
+ def #{name}(*args)
278
+ scoping = scopes[:#{name}]
279
+ scope, extension = scoping[:scope][*args], scoping[:extension]
280
+ criteria = with_default_scope.merge(scope)
281
+ criteria.extend(extension)
282
+ criteria
283
+ end
284
+ SCOPE
285
+ end
286
+
287
+ # When inheriting, we want to copy the scopes from the parent class and
288
+ # set the on the child to start, mimicking the behaviour of the old
289
+ # class_inheritable_accessor that was deprecated in Rails edge.
290
+ #
291
+ # @api private
292
+ #
293
+ # @example Inherit from this class.
294
+ # Person.inherited(Doctor)
295
+ #
296
+ # @param [ Class ] subclass The inheriting class.
297
+ #
298
+ # @since 2.0.0.rc.6
299
+ def inherited(subclass)
300
+ super
301
+ subclass.scopes = scopes.dup
302
+ end
303
+
304
+ # Strip the default scope from the provided value, if it is a criteria.
305
+ # This is used by named scopes - they should not have the default scoping
306
+ # applied to them.
307
+ #
308
+ # @api private
309
+ #
310
+ # @example Strip the default scope.
311
+ # Model.strip_default_scope
312
+ #
313
+ # @param [ Proc, Criteria ] value The value to strip from.
314
+ #
315
+ # @return [ Proc ] The stripped criteria, as a proc.
316
+ #
317
+ # @since 3.0.0
318
+ def strip_default_scope(value)
319
+ if value.is_a?(Criteria)
320
+ default = default_scoping.try(:call)
321
+ value.remove_scoping(default)
322
+ value.to_proc
323
+ else
324
+ value
325
+ end
326
+ end
327
+ end
328
+ end
329
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
2
+ module Mongoid
3
3
 
4
4
  # This module provides the extra behaviour for including relations in JSON
5
5
  # and XML serialization.
@@ -33,7 +33,7 @@ module Mongoid # :nodoc:
33
33
 
34
34
  except |= ['_type'] unless Mongoid.include_type_for_serialization
35
35
 
36
- field_names = fields.keys.map { |field| field.to_s }
36
+ field_names = self.class.attribute_names
37
37
  attribute_names = (as_document.keys + field_names).sort
38
38
  if only.any?
39
39
  attribute_names &= only
@@ -45,38 +45,21 @@ module Mongoid # :nodoc:
45
45
  name.to_s if respond_to?(name)
46
46
  end.compact
47
47
 
48
- {}.tap do |attrs|
49
- (attribute_names + method_names).each do |name|
50
- value = send(name)
48
+ attrs = {}
49
+ (attribute_names + method_names).each do |name|
50
+ without_autobuild do
51
51
  if relations.has_key?(name)
52
- attrs[name] = value.serializable_hash(options)
52
+ value = send(name)
53
+ attrs[name] = value ? value.serializable_hash(options) : nil
54
+ elsif attribute_names.include?(name) && !fields.has_key?(name)
55
+ attrs[name] = read_attribute(name)
53
56
  else
54
- attrs[name] = value
57
+ attrs[name] = send(name)
55
58
  end
56
59
  end
57
- serialize_relations(attrs, options) if options[:include]
58
- end
59
- end
60
-
61
- class << self
62
-
63
- # Serialize the provided object into a Mongo friendly value, using the
64
- # field serialization method for the passed in type. If no type is
65
- # given then we assume generic object serialization, which just returns
66
- # the value itself.
67
- #
68
- # @example Mongoize the object.
69
- # Mongoid::Serialization.mongoize(time, Time)
70
- #
71
- # @param [ Object ] object The object to convert.
72
- # @param [ Class ] klass The type of the object.
73
- #
74
- # @return [ Object ] The converted object.
75
- #
76
- # @since 2.1.0
77
- def mongoize(object, klass = Object)
78
- Fields::Mappings.for(klass).instantiate(:mongoize).serialize(object)
79
60
  end
61
+ serialize_relations(attrs, options) if options[:include]
62
+ attrs
80
63
  end
81
64
 
82
65
  private
@@ -137,7 +120,7 @@ module Mongoid # :nodoc:
137
120
  if inclusions.is_a?(Hash)
138
121
  inclusions[name]
139
122
  else
140
- { :except => options[:except], :only => options[:only] }
123
+ { except: options[:except], only: options[:only] }
141
124
  end
142
125
  end
143
126
  end
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+ require "mongoid/sessions/mongo_uri"
3
+
4
+ module Mongoid
5
+ module Sessions
6
+ module Factory
7
+ extend self
8
+
9
+ # Create a new session given the named configuration. If no name is
10
+ # provided, return a new session with the default configuration. If a
11
+ # name is provided for which no configuration exists, an error will be
12
+ # raised.
13
+ #
14
+ # @example Create the session.
15
+ # Factory.create(:secondary)
16
+ #
17
+ # @param [ String, Symbol ] name The named session configuration.
18
+ #
19
+ # @raise [ Errors::NoSessionConfig ] If no config could be found.
20
+ #
21
+ # @return [ Moped::Session ] The new session.
22
+ #
23
+ # @since 3.0.0
24
+ def create(name = nil)
25
+ return default unless name
26
+ config = Mongoid.sessions[name]
27
+ raise Errors::NoSessionConfig.new(name) unless config
28
+ create_session(config)
29
+ end
30
+
31
+ # Get the default session.
32
+ #
33
+ # @example Get the default session.
34
+ # Factory.default
35
+ #
36
+ # @raise [ Errors::NoSessionConfig ] If no default configuration is
37
+ # found.
38
+ #
39
+ # @return [ Moped::Session ] The default session.
40
+ #
41
+ # @since 3.0.0
42
+ def default
43
+ create_session(Mongoid.sessions[:default])
44
+ end
45
+
46
+ private
47
+
48
+ # Create the session for the provided config.
49
+ #
50
+ # @api private
51
+ #
52
+ # @example Create the session.
53
+ # Factory.create_session(config)
54
+ #
55
+ # @param [ Hash ] configuration The session config.
56
+ #
57
+ # @return [ Moped::Session ] The session.
58
+ #
59
+ # @since 3.0.0
60
+ def create_session(configuration)
61
+ config, options = parse(configuration)
62
+ session = Moped::Session.new(config[:hosts], options)
63
+ session.use(config[:database])
64
+ if authenticated?(config)
65
+ session.login(config[:username], config[:password])
66
+ end
67
+ session
68
+ end
69
+
70
+ # Are we authenticated with this session config?
71
+ #
72
+ # @api private
73
+ #
74
+ # @example Is this session authenticated?
75
+ # Factory.authenticated?(config)
76
+ #
77
+ # @param [ Hash ] config The session config.
78
+ #
79
+ # @return [ true, false ] If we are authenticated.
80
+ #
81
+ # @since 3.0.0
82
+ def authenticated?(config)
83
+ config.has_key?(:username) && config.has_key?(:password)
84
+ end
85
+
86
+ # Parse the configuration. If a uri is provided we need to extract the
87
+ # elements of it, otherwise the options are left alone.
88
+ #
89
+ # @api private
90
+ #
91
+ # @example Parse the config.
92
+ # Factory.parse(config)
93
+ #
94
+ # @param [ Hash ] config The configuration.
95
+ #
96
+ # @return [ Array<Hash> ] The configuration, parsed.
97
+ #
98
+ # @since 3.0.0
99
+ def parse(config)
100
+ options = config[:options].try(:dup) || {}
101
+ parsed = config.has_key?(:uri) ? MongoUri.new(config[:uri]).to_hash : config
102
+ [ parsed, options ]
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Sessions
4
+ class MongoUri
5
+
6
+ SCHEME = /(mongodb:\/\/)/
7
+ USER = /([-.\w:]+)/
8
+ PASS = /([^@,]+)/
9
+ NODES = /((([-.\w]+)(?::(\w+))?,?)+)/
10
+ DATABASE = /(?:\/([-\w]+))?/
11
+
12
+ URI = /#{SCHEME}(#{USER}:#{PASS}@)?#{NODES}#{DATABASE}/
13
+
14
+ attr_reader :match
15
+
16
+ # Get the database provided in the URI.
17
+ #
18
+ # @example Get the database.
19
+ # uri.database
20
+ #
21
+ # @return [ String ] The database.
22
+ #
23
+ # @since 3.0.0
24
+ def database
25
+ @database ||= match[9]
26
+ end
27
+
28
+ # Get the hosts provided in the URI.
29
+ #
30
+ # @example Get the hosts.
31
+ # uri.hosts
32
+ #
33
+ # @return [ Array<String> ] The hosts.
34
+ #
35
+ # @since 3.0.0
36
+ def hosts
37
+ @hosts ||= match[5].split(",")
38
+ end
39
+
40
+ # Create the new uri from the provided string.
41
+ #
42
+ # @example Create the new uri.
43
+ # MongoUri.new(uri)
44
+ #
45
+ # @param [ String ] string The uri string.
46
+ #
47
+ # @since 3.0.0
48
+ def initialize(string)
49
+ @match = string.match(URI)
50
+ end
51
+
52
+ # Get the password provided in the URI.
53
+ #
54
+ # @example Get the password.
55
+ # uri.password
56
+ #
57
+ # @return [ String ] The password.
58
+ #
59
+ # @since 3.0.0
60
+ def password
61
+ @password ||= match[4]
62
+ end
63
+
64
+ # Get the uri as a Mongoid friendly configuration hash.
65
+ #
66
+ # @example Get the uri as a hash.
67
+ # uri.to_hash
68
+ #
69
+ # @return [ Hash ] The uri as options.
70
+ #
71
+ # @since 3.0.0
72
+ def to_hash
73
+ config = { database: database, hosts: hosts }
74
+ if username && password
75
+ config.merge!(username: username, password: password)
76
+ end
77
+ config
78
+ end
79
+
80
+ # Get the username provided in the URI.
81
+ #
82
+ # @example Get the username.
83
+ # uri.username
84
+ #
85
+ # @return [ String ] The username.
86
+ #
87
+ # @since 3.0.0
88
+ def username
89
+ @username ||= match[3]
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Sessions
4
+ module Validators
5
+
6
+ # Validates the options passed to :store_in.
7
+ module Storage
8
+ extend self
9
+
10
+ VALID_OPTIONS = [ :collection, :database, :session ]
11
+
12
+ # Validate the options provided to :store_in.
13
+ #
14
+ # @example Validate the options.
15
+ # Storage.validate(:collection_name)
16
+ #
17
+ # @param [ Class ] klass The model class.
18
+ # @param [ Hash, String, Symbol ] options The provided options.
19
+ #
20
+ # @since 3.0.0
21
+ def validate(klass, options)
22
+ if !options.is_a?(::Hash) || !valid_keys?(options)
23
+ raise Errors::InvalidStorageOptions.new(klass, options)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Determine if all keys in the options hash are valid.
30
+ #
31
+ # @api private
32
+ #
33
+ # @example Are all keys valid?
34
+ # validator.valid_keys?({ collection: "name" })
35
+ #
36
+ # @param [ Hash ] options The options hash.
37
+ #
38
+ # @return [ true, false ] If all keys are valid.
39
+ #
40
+ # @since 3.0.0
41
+ def valid_keys?(options)
42
+ options.keys.all? do |key|
43
+ VALID_OPTIONS.include?(key)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require "mongoid/sessions/validators/storage"