mongoid 2.4.10 → 3.0.0

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 (356) hide show
  1. data/CHANGELOG.md +949 -10
  2. data/LICENSE +1 -1
  3. data/README.md +10 -11
  4. data/Rakefile +3 -17
  5. data/lib/config/locales/en.yml +455 -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 +70 -16
  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 +106 -43
  16. data/lib/mongoid/components.rb +12 -23
  17. data/lib/mongoid/config/environment.rb +7 -4
  18. data/lib/mongoid/config/inflections.rb +6 -0
  19. data/lib/mongoid/config/options.rb +1 -1
  20. data/lib/mongoid/config/validators/option.rb +25 -0
  21. data/lib/mongoid/config/validators/session.rb +140 -0
  22. data/lib/mongoid/config/validators.rb +3 -0
  23. data/lib/mongoid/config.rb +104 -225
  24. data/lib/mongoid/contextual/aggregable/memory.rb +109 -0
  25. data/lib/mongoid/contextual/aggregable/mongo.rb +181 -0
  26. data/lib/mongoid/contextual/atomic.rb +179 -0
  27. data/lib/mongoid/contextual/command.rb +43 -0
  28. data/lib/mongoid/contextual/find_and_modify.rb +68 -0
  29. data/lib/mongoid/contextual/map_reduce.rb +273 -0
  30. data/lib/mongoid/contextual/memory.rb +406 -0
  31. data/lib/mongoid/contextual/mongo.rb +662 -0
  32. data/lib/mongoid/contextual.rb +50 -0
  33. data/lib/mongoid/copyable.rb +7 -25
  34. data/lib/mongoid/criteria.rb +515 -245
  35. data/lib/mongoid/criterion/inspection.rb +14 -8
  36. data/lib/mongoid/criterion/scoping.rb +114 -44
  37. data/lib/mongoid/dirty.rb +152 -67
  38. data/lib/mongoid/document.rb +71 -52
  39. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  40. data/lib/mongoid/errors/callback.rb +5 -6
  41. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  42. data/lib/mongoid/errors/document_not_found.rb +98 -17
  43. data/lib/mongoid/errors/eager_load.rb +3 -6
  44. data/lib/mongoid/errors/invalid_collection.rb +3 -3
  45. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  46. data/lib/mongoid/errors/invalid_database.rb +3 -3
  47. data/lib/mongoid/errors/invalid_field.rb +54 -8
  48. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  49. data/lib/mongoid/errors/invalid_find.rb +3 -3
  50. data/lib/mongoid/errors/invalid_index.rb +28 -0
  51. data/lib/mongoid/errors/invalid_options.rb +4 -4
  52. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  53. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  54. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  55. data/lib/mongoid/errors/invalid_time.rb +3 -6
  56. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  57. data/lib/mongoid/errors/mixed_relations.rb +4 -9
  58. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  59. data/lib/mongoid/errors/mongoid_error.rb +54 -3
  60. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  61. data/lib/mongoid/errors/no_default_session.rb +23 -0
  62. data/lib/mongoid/errors/no_environment.rb +3 -3
  63. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  64. data/lib/mongoid/errors/no_metadata.rb +21 -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 +23 -1
  80. data/lib/mongoid/evolvable.rb +19 -0
  81. data/lib/mongoid/extensions/array.rb +164 -0
  82. data/lib/mongoid/extensions/big_decimal.rb +42 -0
  83. data/lib/mongoid/extensions/boolean.rb +24 -0
  84. data/lib/mongoid/extensions/date.rb +70 -0
  85. data/lib/mongoid/extensions/date_time.rb +73 -0
  86. data/lib/mongoid/extensions/false_class.rb +38 -0
  87. data/lib/mongoid/extensions/float.rb +56 -0
  88. data/lib/mongoid/extensions/hash.rb +123 -0
  89. data/lib/mongoid/extensions/integer.rb +66 -0
  90. data/lib/mongoid/extensions/module.rb +28 -0
  91. data/lib/mongoid/extensions/nil_class.rb +21 -0
  92. data/lib/mongoid/extensions/object.rb +238 -0
  93. data/lib/mongoid/extensions/object_id.rb +54 -0
  94. data/lib/mongoid/extensions/range.rb +79 -0
  95. data/lib/mongoid/extensions/regexp.rb +27 -0
  96. data/lib/mongoid/extensions/set.rb +55 -0
  97. data/lib/mongoid/extensions/string.rb +181 -0
  98. data/lib/mongoid/extensions/symbol.rb +54 -0
  99. data/lib/mongoid/extensions/time.rb +78 -0
  100. data/lib/mongoid/extensions/time_with_zone.rb +55 -0
  101. data/lib/mongoid/extensions/true_class.rb +38 -0
  102. data/lib/mongoid/extensions.rb +28 -76
  103. data/lib/mongoid/factory.rb +1 -1
  104. data/lib/mongoid/fields/foreign_key.rb +150 -0
  105. data/lib/mongoid/fields/localized.rb +73 -0
  106. data/lib/mongoid/fields/standard.rb +268 -0
  107. data/lib/mongoid/fields/validators/macro.rb +83 -0
  108. data/lib/mongoid/fields/validators.rb +2 -0
  109. data/lib/mongoid/fields.rb +142 -208
  110. data/lib/mongoid/finders.rb +45 -50
  111. data/lib/mongoid/hierarchy.rb +44 -15
  112. data/lib/mongoid/identity_map.rb +49 -21
  113. data/lib/mongoid/indexes/validators/options.rb +80 -0
  114. data/lib/mongoid/indexes.rb +66 -15
  115. data/lib/mongoid/inspection.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 +9 -11
  134. data/lib/mongoid/nested_attributes.rb +17 -9
  135. data/lib/mongoid/observer.rb +1 -2
  136. data/lib/mongoid/paranoia.rb +10 -44
  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/upsert.rb +28 -0
  159. data/lib/mongoid/persistence/operations.rb +22 -19
  160. data/lib/mongoid/persistence/upsertion.rb +30 -0
  161. data/lib/mongoid/persistence.rb +94 -39
  162. data/lib/mongoid/railtie.rb +26 -11
  163. data/lib/mongoid/railties/database.rake +22 -108
  164. data/lib/mongoid/relations/accessors.rb +120 -20
  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 +4 -4
  175. data/lib/mongoid/relations/builders/embedded/in.rb +5 -5
  176. data/lib/mongoid/relations/builders/embedded/many.rb +12 -12
  177. data/lib/mongoid/relations/builders/embedded/one.rb +6 -6
  178. data/lib/mongoid/relations/builders/nested_attributes/many.rb +8 -8
  179. data/lib/mongoid/relations/builders/nested_attributes/one.rb +5 -5
  180. data/lib/mongoid/relations/builders/referenced/in.rb +4 -4
  181. data/lib/mongoid/relations/builders/referenced/many.rb +6 -6
  182. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +7 -5
  183. data/lib/mongoid/relations/builders/referenced/one.rb +5 -5
  184. data/lib/mongoid/relations/builders.rb +19 -16
  185. data/lib/mongoid/relations/cascading/delete.rb +3 -5
  186. data/lib/mongoid/relations/cascading/destroy.rb +3 -3
  187. data/lib/mongoid/relations/cascading/nullify.rb +3 -3
  188. data/lib/mongoid/relations/cascading/restrict.rb +37 -0
  189. data/lib/mongoid/relations/cascading.rb +10 -7
  190. data/lib/mongoid/relations/constraint.rb +4 -3
  191. data/lib/mongoid/relations/conversions.rb +6 -7
  192. data/lib/mongoid/relations/cyclic.rb +7 -7
  193. data/lib/mongoid/relations/embedded/batchable.rb +347 -0
  194. data/lib/mongoid/relations/embedded/in.rb +23 -12
  195. data/lib/mongoid/relations/embedded/many.rb +100 -161
  196. data/lib/mongoid/relations/embedded/one.rb +25 -14
  197. data/lib/mongoid/relations/macros.rb +105 -60
  198. data/lib/mongoid/relations/many.rb +93 -14
  199. data/lib/mongoid/relations/metadata.rb +277 -47
  200. data/lib/mongoid/relations/nested_builder.rb +4 -6
  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 +62 -31
  205. data/lib/mongoid/relations/referenced/in.rb +40 -15
  206. data/lib/mongoid/relations/referenced/many.rb +162 -130
  207. data/lib/mongoid/relations/referenced/many_to_many.rb +104 -48
  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/relations/touchable.rb +32 -0
  213. data/lib/mongoid/relations.rb +22 -6
  214. data/lib/mongoid/reloading.rb +12 -14
  215. data/lib/mongoid/scoping.rb +312 -0
  216. data/lib/mongoid/serialization.rb +94 -42
  217. data/lib/mongoid/sessions/factory.rb +108 -0
  218. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  219. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  220. data/lib/mongoid/sessions/validators.rb +2 -0
  221. data/lib/mongoid/sessions.rb +383 -0
  222. data/lib/mongoid/sharding.rb +6 -6
  223. data/lib/mongoid/state.rb +6 -7
  224. data/lib/mongoid/threaded/lifecycle.rb +21 -21
  225. data/lib/mongoid/threaded/sessions.rb +0 -0
  226. data/lib/mongoid/threaded.rb +219 -59
  227. data/lib/mongoid/timestamps/created.rb +8 -4
  228. data/lib/mongoid/timestamps/timeless.rb +6 -4
  229. data/lib/mongoid/timestamps/updated.rb +4 -3
  230. data/lib/mongoid/timestamps.rb +1 -1
  231. data/lib/mongoid/unit_of_work.rb +61 -0
  232. data/lib/mongoid/validations/associated.rb +2 -2
  233. data/lib/mongoid/validations/format.rb +2 -2
  234. data/lib/mongoid/validations/presence.rb +34 -4
  235. data/lib/mongoid/validations/uniqueness.rb +11 -12
  236. data/lib/mongoid/validations.rb +28 -20
  237. data/lib/mongoid/version.rb +2 -2
  238. data/lib/mongoid/versioning.rb +25 -26
  239. data/lib/mongoid.rb +37 -37
  240. data/lib/rack/mongoid/middleware/identity_map.rb +3 -3
  241. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -1
  242. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +65 -17
  243. data/lib/rails/generators/mongoid/model/model_generator.rb +7 -7
  244. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +2 -2
  245. data/lib/rails/generators/mongoid/observer/observer_generator.rb +4 -4
  246. data/lib/rails/generators/mongoid_generator.rb +5 -5
  247. data/lib/rails/mongoid.rb +73 -26
  248. metadata +103 -148
  249. data/lib/config/locales/bg.yml +0 -61
  250. data/lib/config/locales/de.yml +0 -61
  251. data/lib/config/locales/en-GB.yml +0 -64
  252. data/lib/config/locales/es.yml +0 -59
  253. data/lib/config/locales/fr.yml +0 -62
  254. data/lib/config/locales/hi.yml +0 -53
  255. data/lib/config/locales/hu.yml +0 -64
  256. data/lib/config/locales/id.yml +0 -62
  257. data/lib/config/locales/it.yml +0 -59
  258. data/lib/config/locales/ja.yml +0 -57
  259. data/lib/config/locales/kr.yml +0 -54
  260. data/lib/config/locales/nl.yml +0 -61
  261. data/lib/config/locales/pl.yml +0 -59
  262. data/lib/config/locales/pt-BR.yml +0 -60
  263. data/lib/config/locales/pt.yml +0 -60
  264. data/lib/config/locales/ro.yml +0 -66
  265. data/lib/config/locales/ru.yml +0 -61
  266. data/lib/config/locales/sv.yml +0 -60
  267. data/lib/config/locales/vi.yml +0 -62
  268. data/lib/config/locales/zh-CN.yml +0 -53
  269. data/lib/mongoid/collection.rb +0 -157
  270. data/lib/mongoid/collections/master.rb +0 -45
  271. data/lib/mongoid/collections/operations.rb +0 -44
  272. data/lib/mongoid/collections/retry.rb +0 -59
  273. data/lib/mongoid/collections.rb +0 -120
  274. data/lib/mongoid/config/database.rb +0 -181
  275. data/lib/mongoid/config/replset_database.rb +0 -80
  276. data/lib/mongoid/contexts/enumerable/sort.rb +0 -43
  277. data/lib/mongoid/contexts/enumerable.rb +0 -313
  278. data/lib/mongoid/contexts/mongo.rb +0 -487
  279. data/lib/mongoid/contexts.rb +0 -25
  280. data/lib/mongoid/criterion/builder.rb +0 -34
  281. data/lib/mongoid/criterion/complex.rb +0 -84
  282. data/lib/mongoid/criterion/creational.rb +0 -34
  283. data/lib/mongoid/criterion/exclusion.rb +0 -108
  284. data/lib/mongoid/criterion/inclusion.rb +0 -290
  285. data/lib/mongoid/criterion/optional.rb +0 -259
  286. data/lib/mongoid/criterion/selector.rb +0 -177
  287. data/lib/mongoid/cursor.rb +0 -88
  288. data/lib/mongoid/default_scope.rb +0 -36
  289. data/lib/mongoid/errors/invalid_type.rb +0 -25
  290. data/lib/mongoid/extensions/array/deep_copy.rb +0 -25
  291. data/lib/mongoid/extensions/array/deletion.rb +0 -29
  292. data/lib/mongoid/extensions/false_class/equality.rb +0 -26
  293. data/lib/mongoid/extensions/hash/criteria_helpers.rb +0 -47
  294. data/lib/mongoid/extensions/hash/deep_copy.rb +0 -25
  295. data/lib/mongoid/extensions/hash/scoping.rb +0 -25
  296. data/lib/mongoid/extensions/integer/checks.rb +0 -23
  297. data/lib/mongoid/extensions/nil/collectionization.rb +0 -23
  298. data/lib/mongoid/extensions/object/checks.rb +0 -29
  299. data/lib/mongoid/extensions/object/deep_copy.rb +0 -21
  300. data/lib/mongoid/extensions/object/reflections.rb +0 -48
  301. data/lib/mongoid/extensions/object/substitutable.rb +0 -15
  302. data/lib/mongoid/extensions/object/yoda.rb +0 -44
  303. data/lib/mongoid/extensions/object_id/conversions.rb +0 -60
  304. data/lib/mongoid/extensions/proc/scoping.rb +0 -25
  305. data/lib/mongoid/extensions/string/checks.rb +0 -36
  306. data/lib/mongoid/extensions/string/conversions.rb +0 -22
  307. data/lib/mongoid/extensions/string/inflections.rb +0 -118
  308. data/lib/mongoid/extensions/symbol/checks.rb +0 -23
  309. data/lib/mongoid/extensions/symbol/inflections.rb +0 -67
  310. data/lib/mongoid/extensions/true_class/equality.rb +0 -26
  311. data/lib/mongoid/extras.rb +0 -31
  312. data/lib/mongoid/fields/internal/array.rb +0 -76
  313. data/lib/mongoid/fields/internal/big_decimal.rb +0 -63
  314. data/lib/mongoid/fields/internal/bignum.rb +0 -10
  315. data/lib/mongoid/fields/internal/binary.rb +0 -11
  316. data/lib/mongoid/fields/internal/boolean.rb +0 -58
  317. data/lib/mongoid/fields/internal/date.rb +0 -51
  318. data/lib/mongoid/fields/internal/date_time.rb +0 -28
  319. data/lib/mongoid/fields/internal/false_class.rb +0 -10
  320. data/lib/mongoid/fields/internal/fixnum.rb +0 -10
  321. data/lib/mongoid/fields/internal/float.rb +0 -47
  322. data/lib/mongoid/fields/internal/foreign_keys/array.rb +0 -88
  323. data/lib/mongoid/fields/internal/foreign_keys/object.rb +0 -56
  324. data/lib/mongoid/fields/internal/hash.rb +0 -11
  325. data/lib/mongoid/fields/internal/integer.rb +0 -59
  326. data/lib/mongoid/fields/internal/localized.rb +0 -62
  327. data/lib/mongoid/fields/internal/nil_class.rb +0 -53
  328. data/lib/mongoid/fields/internal/object.rb +0 -11
  329. data/lib/mongoid/fields/internal/object_id.rb +0 -46
  330. data/lib/mongoid/fields/internal/range.rb +0 -61
  331. data/lib/mongoid/fields/internal/set.rb +0 -57
  332. data/lib/mongoid/fields/internal/string.rb +0 -42
  333. data/lib/mongoid/fields/internal/symbol.rb +0 -43
  334. data/lib/mongoid/fields/internal/time.rb +0 -23
  335. data/lib/mongoid/fields/internal/time_with_zone.rb +0 -23
  336. data/lib/mongoid/fields/internal/timekeeping.rb +0 -122
  337. data/lib/mongoid/fields/internal/true_class.rb +0 -10
  338. data/lib/mongoid/fields/mappings.rb +0 -42
  339. data/lib/mongoid/fields/serializable.rb +0 -270
  340. data/lib/mongoid/identity.rb +0 -92
  341. data/lib/mongoid/javascript/functions.yml +0 -63
  342. data/lib/mongoid/javascript.rb +0 -20
  343. data/lib/mongoid/keys.rb +0 -144
  344. data/lib/mongoid/logger.rb +0 -45
  345. data/lib/mongoid/multi_database.rb +0 -36
  346. data/lib/mongoid/named_scope.rb +0 -166
  347. data/lib/mongoid/relations/embedded/atomic/operation.rb +0 -63
  348. data/lib/mongoid/relations/embedded/atomic/pull.rb +0 -65
  349. data/lib/mongoid/relations/embedded/atomic/push_all.rb +0 -59
  350. data/lib/mongoid/relations/embedded/atomic/set.rb +0 -61
  351. data/lib/mongoid/relations/embedded/atomic/unset.rb +0 -41
  352. data/lib/mongoid/relations/embedded/atomic.rb +0 -89
  353. data/lib/mongoid/relations/referenced/batch/insert.rb +0 -57
  354. data/lib/mongoid/relations/referenced/batch.rb +0 -73
  355. data/lib/mongoid/safety.rb +0 -105
  356. data/lib/mongoid/scope.rb +0 -31
@@ -0,0 +1,312 @@
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
+ # Strip the default scope from the provided value, if it is a criteria.
288
+ # This is used by named scopes - they should not have the default scoping
289
+ # applied to them.
290
+ #
291
+ # @api private
292
+ #
293
+ # @example Strip the default scope.
294
+ # Model.strip_default_scope
295
+ #
296
+ # @param [ Proc, Criteria ] value The value to strip from.
297
+ #
298
+ # @return [ Proc ] The stripped criteria, as a proc.
299
+ #
300
+ # @since 3.0.0
301
+ def strip_default_scope(value)
302
+ if value.is_a?(Criteria)
303
+ default = default_scoping.try(:call)
304
+ value.remove_scoping(default)
305
+ value.to_proc
306
+ else
307
+ value
308
+ end
309
+ end
310
+ end
311
+ end
312
+ 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.
@@ -27,59 +27,111 @@ module Mongoid # :nodoc:
27
27
  # @since 2.0.0.rc.6
28
28
  def serializable_hash(options = nil)
29
29
  options ||= {}
30
+ attrs = {}
30
31
 
31
- only = Array.wrap(options[:only]).map(&:to_s)
32
- except = Array.wrap(options[:except]).map(&:to_s)
33
-
34
- except |= ['_type'] unless Mongoid.include_type_for_serialization
35
-
36
- field_names = fields.keys.map { |field| field.to_s }
37
- attribute_names = (as_document.keys + field_names).sort
38
- if only.any?
39
- attribute_names &= only
40
- elsif except.any?
41
- attribute_names -= except
42
- end
32
+ names = field_names(options)
43
33
 
44
- method_names = Array.wrap(options[:methods]).map do |name|
45
- name.to_s if respond_to?(name)
46
- end.compact
34
+ _serializing do
35
+ method_names = Array.wrap(options[:methods]).map do |name|
36
+ name.to_s if respond_to?(name)
37
+ end.compact
47
38
 
48
- {}.tap do |attrs|
49
- (attribute_names + method_names).each do |name|
50
- value = send(name)
51
- if relations.has_key?(name)
52
- attrs[name] = value.serializable_hash(options)
53
- else
54
- attrs[name] = value
39
+ (names + method_names).each do |name|
40
+ without_autobuild do
41
+ serialize_attribute(attrs, name, names, options)
55
42
  end
56
43
  end
57
44
  serialize_relations(attrs, options) if options[:include]
58
45
  end
46
+ attrs
47
+ end
48
+
49
+ private
50
+
51
+ # Enter the serialization block.
52
+ #
53
+ # @api private
54
+ #
55
+ # @example Begin serialization.
56
+ # document._serializing do
57
+ # end
58
+ #
59
+ # @return [ Object ] The result of the yield.
60
+ #
61
+ # @since 3.0.0
62
+ def _serializing
63
+ Threaded.begin("serialization")
64
+ yield
65
+ ensure
66
+ Threaded.exit("serialization")
59
67
  end
60
68
 
61
- class << self
69
+ # Are we in a serialization block? We use this to protect multiple
70
+ # unnecessary calls to #as_document.
71
+ #
72
+ # @api private
73
+ #
74
+ # @example Are we in serialization?
75
+ # document._serializing?
76
+ #
77
+ # @return [ true, false ] If we are serializing.
78
+ #
79
+ # @since 3.0.0
80
+ def _serializing?
81
+ Threaded.executing?("serialization")
82
+ end
62
83
 
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)
84
+ # Get the names of all fields that will be serialized.
85
+ #
86
+ # @api private
87
+ #
88
+ # @example Get all the field names.
89
+ # document.send(:field_names)
90
+ #
91
+ # @return [ Array<String> ] The names of the fields.
92
+ #
93
+ # @since 3.0.0
94
+ def field_names(options)
95
+ names = (_serializing? ? attribute_names : as_document.keys + attribute_names).uniq.sort
96
+
97
+ only = Array.wrap(options[:only]).map(&:to_s)
98
+ except = Array.wrap(options[:except]).map(&:to_s)
99
+ except |= ['_type'] unless Mongoid.include_type_for_serialization
100
+
101
+ if !only.empty?
102
+ names &= only
103
+ elsif !except.empty?
104
+ names -= except
79
105
  end
106
+ names
80
107
  end
81
108
 
82
- private
109
+ # Serialize a single attribute. Handles relations, fields, and dynamic
110
+ # attributes.
111
+ #
112
+ # @api private
113
+ #
114
+ # @example Serialize the attribute.
115
+ # document.serialize_attribute({}, "id" , [ "id" ])
116
+ #
117
+ # @param [ Hash ] attrs The attributes.
118
+ # @param [ String ] name The attribute name.
119
+ # @param [ Array<String> ] names The names of all attributes.
120
+ # @param [ Hash ] options The options.
121
+ #
122
+ # @return [ Object ] The attribute.
123
+ #
124
+ # @since 3.0.0
125
+ def serialize_attribute(attrs, name, names, options)
126
+ if relations.has_key?(name)
127
+ value = send(name)
128
+ attrs[name] = value ? value.serializable_hash(options) : nil
129
+ elsif names.include?(name) && !fields.has_key?(name)
130
+ attrs[name] = read_attribute(name)
131
+ else
132
+ attrs[name] = send(name)
133
+ end
134
+ end
83
135
 
84
136
  # For each of the provided include options, get the relation needed and
85
137
  # provide it in the hash.
@@ -137,7 +189,7 @@ module Mongoid # :nodoc:
137
189
  if inclusions.is_a?(Hash)
138
190
  inclusions[name]
139
191
  else
140
- { :except => options[:except], :only => options[:only] }
192
+ { except: options[:except], only: options[:only] }
141
193
  end
142
194
  end
143
195
  end
@@ -0,0 +1,108 @@
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
+ raise Errors::NoSessionsConfig.new unless configuration
62
+ config, options = parse(configuration)
63
+ configuration.merge!(config) if configuration.delete(:uri)
64
+ session = Moped::Session.new(config[:hosts], options)
65
+ session.use(config[:database])
66
+ if authenticated?(config)
67
+ session.login(config[:username], config[:password])
68
+ end
69
+ session
70
+ end
71
+
72
+ # Are we authenticated with this session config?
73
+ #
74
+ # @api private
75
+ #
76
+ # @example Is this session authenticated?
77
+ # Factory.authenticated?(config)
78
+ #
79
+ # @param [ Hash ] config The session config.
80
+ #
81
+ # @return [ true, false ] If we are authenticated.
82
+ #
83
+ # @since 3.0.0
84
+ def authenticated?(config)
85
+ config.has_key?(:username) && config.has_key?(:password)
86
+ end
87
+
88
+ # Parse the configuration. If a uri is provided we need to extract the
89
+ # elements of it, otherwise the options are left alone.
90
+ #
91
+ # @api private
92
+ #
93
+ # @example Parse the config.
94
+ # Factory.parse(config)
95
+ #
96
+ # @param [ Hash ] config The configuration.
97
+ #
98
+ # @return [ Array<Hash> ] The configuration, parsed.
99
+ #
100
+ # @since 3.0.0
101
+ def parse(config)
102
+ options = config[:options].try(:dup) || {}
103
+ parsed = config.has_key?(:uri) ? MongoUri.new(config[:uri]).to_hash : config
104
+ [ parsed, options ]
105
+ end
106
+ end
107
+ end
108
+ 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