mongoid 2.8.1 → 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 +802 -58
  2. data/LICENSE +1 -1
  3. data/README.md +10 -11
  4. data/Rakefile +2 -8
  5. data/lib/config/locales/en.yml +441 -51
  6. data/lib/mongoid.rb +24 -39
  7. data/lib/mongoid/atomic.rb +16 -33
  8. data/lib/mongoid/atomic/modifiers.rb +2 -2
  9. data/lib/mongoid/atomic/paths/embedded.rb +4 -5
  10. data/lib/mongoid/atomic/paths/embedded/many.rb +6 -6
  11. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -5
  12. data/lib/mongoid/atomic/paths/root.rb +4 -5
  13. data/lib/mongoid/attributes.rb +95 -32
  14. data/lib/mongoid/attributes/processing.rb +14 -10
  15. data/lib/mongoid/attributes/readonly.rb +56 -0
  16. data/lib/mongoid/callbacks.rb +90 -27
  17. data/lib/mongoid/collections/retry.rb +2 -3
  18. data/lib/mongoid/components.rb +11 -23
  19. data/lib/mongoid/config.rb +87 -233
  20. data/lib/mongoid/config/environment.rb +5 -6
  21. data/lib/mongoid/config/inflections.rb +6 -0
  22. data/lib/mongoid/config/options.rb +1 -1
  23. data/lib/mongoid/config/validators.rb +3 -0
  24. data/lib/mongoid/config/validators/option.rb +25 -0
  25. data/lib/mongoid/config/validators/session.rb +140 -0
  26. data/lib/mongoid/contextual.rb +50 -0
  27. data/lib/mongoid/contextual/aggregable/memory.rb +98 -0
  28. data/lib/mongoid/contextual/aggregable/mongo.rb +181 -0
  29. data/lib/mongoid/contextual/atomic.rb +179 -0
  30. data/lib/mongoid/contextual/command.rb +43 -0
  31. data/lib/mongoid/contextual/find_and_modify.rb +66 -0
  32. data/lib/mongoid/contextual/map_reduce.rb +273 -0
  33. data/lib/mongoid/contextual/memory.rb +383 -0
  34. data/lib/mongoid/contextual/mongo.rb +543 -0
  35. data/lib/mongoid/copyable.rb +3 -34
  36. data/lib/mongoid/criteria.rb +436 -250
  37. data/lib/mongoid/criterion/inspection.rb +14 -8
  38. data/lib/mongoid/criterion/scoping.rb +114 -44
  39. data/lib/mongoid/dirty.rb +152 -67
  40. data/lib/mongoid/document.rb +69 -50
  41. data/lib/mongoid/errors.rb +22 -1
  42. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  43. data/lib/mongoid/errors/callback.rb +5 -6
  44. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  45. data/lib/mongoid/errors/document_not_found.rb +98 -17
  46. data/lib/mongoid/errors/eager_load.rb +3 -6
  47. data/lib/mongoid/errors/invalid_collection.rb +3 -3
  48. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  49. data/lib/mongoid/errors/invalid_database.rb +3 -3
  50. data/lib/mongoid/errors/invalid_field.rb +54 -8
  51. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  52. data/lib/mongoid/errors/invalid_find.rb +3 -3
  53. data/lib/mongoid/errors/invalid_index.rb +28 -0
  54. data/lib/mongoid/errors/invalid_options.rb +4 -4
  55. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  56. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  57. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  58. data/lib/mongoid/errors/invalid_time.rb +3 -6
  59. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  60. data/lib/mongoid/errors/mixed_relations.rb +4 -9
  61. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  62. data/lib/mongoid/errors/mongoid_error.rb +54 -3
  63. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  64. data/lib/mongoid/errors/no_default_session.rb +23 -0
  65. data/lib/mongoid/errors/no_environment.rb +3 -3
  66. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  67. data/lib/mongoid/errors/no_parent.rb +24 -0
  68. data/lib/mongoid/errors/no_session_config.rb +22 -0
  69. data/lib/mongoid/errors/no_session_database.rb +27 -0
  70. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  71. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  72. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  73. data/lib/mongoid/errors/scope_overwrite.rb +4 -4
  74. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +4 -4
  75. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  76. data/lib/mongoid/errors/unsaved_document.rb +4 -8
  77. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  78. data/lib/mongoid/errors/unsupported_version.rb +4 -4
  79. data/lib/mongoid/errors/validations.rb +7 -6
  80. data/lib/mongoid/errors/versioning_not_on_root.rb +23 -0
  81. data/lib/mongoid/extensions.rb +28 -76
  82. data/lib/mongoid/extensions/array.rb +127 -0
  83. data/lib/mongoid/extensions/big_decimal.rb +42 -0
  84. data/lib/mongoid/extensions/boolean.rb +24 -0
  85. data/lib/mongoid/extensions/date.rb +70 -0
  86. data/lib/mongoid/extensions/date_time.rb +68 -0
  87. data/lib/mongoid/extensions/false_class.rb +26 -0
  88. data/lib/mongoid/extensions/float.rb +44 -0
  89. data/lib/mongoid/extensions/hash.rb +91 -0
  90. data/lib/mongoid/extensions/integer.rb +54 -0
  91. data/lib/mongoid/extensions/module.rb +28 -0
  92. data/lib/mongoid/extensions/nil_class.rb +21 -0
  93. data/lib/mongoid/extensions/object.rb +188 -0
  94. data/lib/mongoid/extensions/object_id.rb +53 -0
  95. data/lib/mongoid/extensions/range.rb +55 -0
  96. data/lib/mongoid/extensions/regexp.rb +27 -0
  97. data/lib/mongoid/extensions/set.rb +55 -0
  98. data/lib/mongoid/extensions/string.rb +155 -0
  99. data/lib/mongoid/extensions/symbol.rb +54 -0
  100. data/lib/mongoid/extensions/time.rb +78 -0
  101. data/lib/mongoid/extensions/time_with_zone.rb +55 -0
  102. data/lib/mongoid/extensions/true_class.rb +26 -0
  103. data/lib/mongoid/factory.rb +1 -1
  104. data/lib/mongoid/fields.rb +129 -194
  105. data/lib/mongoid/fields/foreign_key.rb +134 -0
  106. data/lib/mongoid/fields/localized.rb +73 -0
  107. data/lib/mongoid/fields/standard.rb +268 -0
  108. data/lib/mongoid/fields/validators.rb +2 -0
  109. data/lib/mongoid/fields/validators/macro.rb +83 -0
  110. data/lib/mongoid/finders.rb +42 -43
  111. data/lib/mongoid/hierarchy.rb +25 -14
  112. data/lib/mongoid/identity_map.rb +31 -19
  113. data/lib/mongoid/indexes.rb +66 -15
  114. data/lib/mongoid/indexes/validators/options.rb +80 -0
  115. data/lib/mongoid/inspection.rb +1 -1
  116. data/lib/mongoid/javascript.rb +1 -1
  117. data/lib/mongoid/json.rb +2 -2
  118. data/lib/mongoid/loggable.rb +69 -0
  119. data/lib/mongoid/matchers.rb +1 -1
  120. data/lib/mongoid/matchers/all.rb +7 -8
  121. data/lib/mongoid/matchers/and.rb +3 -3
  122. data/lib/mongoid/matchers/default.rb +6 -4
  123. data/lib/mongoid/matchers/exists.rb +2 -2
  124. data/lib/mongoid/matchers/gt.rb +2 -2
  125. data/lib/mongoid/matchers/gte.rb +2 -2
  126. data/lib/mongoid/matchers/in.rb +3 -7
  127. data/lib/mongoid/matchers/lt.rb +2 -2
  128. data/lib/mongoid/matchers/lte.rb +2 -2
  129. data/lib/mongoid/matchers/ne.rb +2 -2
  130. data/lib/mongoid/matchers/nin.rb +2 -2
  131. data/lib/mongoid/matchers/or.rb +2 -2
  132. data/lib/mongoid/matchers/size.rb +2 -2
  133. data/lib/mongoid/matchers/strategies.rb +3 -3
  134. data/lib/mongoid/multi_parameter_attributes.rb +8 -10
  135. data/lib/mongoid/nested_attributes.rb +17 -9
  136. data/lib/mongoid/observer.rb +1 -2
  137. data/lib/mongoid/paranoia.rb +13 -18
  138. data/lib/mongoid/persistence.rb +43 -39
  139. data/lib/mongoid/persistence/atomic.rb +2 -2
  140. data/lib/mongoid/persistence/atomic/add_to_set.rb +5 -9
  141. data/lib/mongoid/persistence/atomic/bit.rb +5 -7
  142. data/lib/mongoid/persistence/atomic/inc.rb +5 -7
  143. data/lib/mongoid/persistence/atomic/operation.rb +45 -6
  144. data/lib/mongoid/persistence/atomic/pop.rb +5 -7
  145. data/lib/mongoid/persistence/atomic/pull.rb +5 -7
  146. data/lib/mongoid/persistence/atomic/pull_all.rb +5 -7
  147. data/lib/mongoid/persistence/atomic/push.rb +4 -10
  148. data/lib/mongoid/persistence/atomic/push_all.rb +4 -10
  149. data/lib/mongoid/persistence/atomic/rename.rb +6 -7
  150. data/lib/mongoid/persistence/atomic/sets.rb +5 -7
  151. data/lib/mongoid/persistence/atomic/unset.rb +4 -5
  152. data/lib/mongoid/persistence/deletion.rb +2 -2
  153. data/lib/mongoid/persistence/insertion.rb +10 -16
  154. data/lib/mongoid/persistence/modification.rb +5 -9
  155. data/lib/mongoid/persistence/operations.rb +6 -19
  156. data/lib/mongoid/persistence/operations/embedded/insert.rb +7 -6
  157. data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -5
  158. data/lib/mongoid/persistence/operations/insert.rb +4 -4
  159. data/lib/mongoid/persistence/operations/remove.rb +4 -4
  160. data/lib/mongoid/persistence/operations/update.rb +5 -5
  161. data/lib/mongoid/railtie.rb +26 -11
  162. data/lib/mongoid/railties/database.rake +22 -108
  163. data/lib/mongoid/relations.rb +4 -6
  164. data/lib/mongoid/relations/accessors.rb +119 -19
  165. data/lib/mongoid/relations/auto_save.rb +59 -5
  166. data/lib/mongoid/relations/binding.rb +211 -2
  167. data/lib/mongoid/relations/bindings/embedded/in.rb +16 -22
  168. data/lib/mongoid/relations/bindings/embedded/many.rb +9 -50
  169. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -16
  170. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -57
  171. data/lib/mongoid/relations/bindings/referenced/many.rb +8 -20
  172. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -19
  173. data/lib/mongoid/relations/bindings/referenced/one.rb +10 -24
  174. data/lib/mongoid/relations/builder.rb +3 -3
  175. data/lib/mongoid/relations/builders.rb +19 -16
  176. data/lib/mongoid/relations/builders/embedded/in.rb +5 -5
  177. data/lib/mongoid/relations/builders/embedded/many.rb +12 -12
  178. data/lib/mongoid/relations/builders/embedded/one.rb +6 -6
  179. data/lib/mongoid/relations/builders/nested_attributes/many.rb +8 -8
  180. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -4
  181. data/lib/mongoid/relations/builders/referenced/in.rb +4 -4
  182. data/lib/mongoid/relations/builders/referenced/many.rb +5 -5
  183. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +7 -5
  184. data/lib/mongoid/relations/builders/referenced/one.rb +5 -5
  185. data/lib/mongoid/relations/cascading.rb +6 -4
  186. data/lib/mongoid/relations/cascading/delete.rb +3 -5
  187. data/lib/mongoid/relations/cascading/destroy.rb +3 -3
  188. data/lib/mongoid/relations/cascading/nullify.rb +3 -3
  189. data/lib/mongoid/relations/cascading/restrict.rb +37 -0
  190. data/lib/mongoid/relations/constraint.rb +4 -3
  191. data/lib/mongoid/relations/conversions.rb +5 -6
  192. data/lib/mongoid/relations/cyclic.rb +7 -7
  193. data/lib/mongoid/relations/embedded/batchable.rb +346 -0
  194. data/lib/mongoid/relations/embedded/in.rb +23 -12
  195. data/lib/mongoid/relations/embedded/many.rb +99 -161
  196. data/lib/mongoid/relations/embedded/one.rb +25 -14
  197. data/lib/mongoid/relations/macros.rb +105 -61
  198. data/lib/mongoid/relations/many.rb +93 -14
  199. data/lib/mongoid/relations/metadata.rb +200 -45
  200. data/lib/mongoid/relations/nested_builder.rb +3 -5
  201. data/lib/mongoid/relations/one.rb +2 -2
  202. data/lib/mongoid/relations/options.rb +2 -2
  203. data/lib/mongoid/relations/polymorphic.rb +9 -9
  204. data/lib/mongoid/relations/proxy.rb +60 -31
  205. data/lib/mongoid/relations/referenced/in.rb +40 -15
  206. data/lib/mongoid/relations/referenced/many.rb +117 -132
  207. data/lib/mongoid/relations/referenced/many_to_many.rb +101 -46
  208. data/lib/mongoid/relations/referenced/one.rb +34 -13
  209. data/lib/mongoid/relations/reflections.rb +3 -3
  210. data/lib/mongoid/relations/synchronization.rb +19 -23
  211. data/lib/mongoid/relations/targets/enumerable.rb +86 -57
  212. data/lib/mongoid/reloading.rb +12 -14
  213. data/lib/mongoid/scoping.rb +329 -0
  214. data/lib/mongoid/serialization.rb +8 -27
  215. data/lib/mongoid/sessions.rb +359 -0
  216. data/lib/mongoid/sessions/factory.rb +106 -0
  217. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  218. data/lib/mongoid/sessions/validators.rb +2 -0
  219. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  220. data/lib/mongoid/sharding.rb +6 -6
  221. data/lib/mongoid/state.rb +6 -7
  222. data/lib/mongoid/threaded.rb +167 -59
  223. data/lib/mongoid/threaded/lifecycle.rb +21 -22
  224. data/lib/mongoid/threaded/sessions.rb +0 -0
  225. data/lib/mongoid/timestamps.rb +1 -1
  226. data/lib/mongoid/timestamps/created.rb +8 -4
  227. data/lib/mongoid/timestamps/timeless.rb +6 -4
  228. data/lib/mongoid/timestamps/updated.rb +3 -3
  229. data/lib/mongoid/unit_of_work.rb +61 -0
  230. data/lib/mongoid/validations.rb +27 -19
  231. data/lib/mongoid/validations/associated.rb +2 -2
  232. data/lib/mongoid/validations/format.rb +2 -2
  233. data/lib/mongoid/validations/presence.rb +31 -5
  234. data/lib/mongoid/validations/uniqueness.rb +9 -12
  235. data/lib/mongoid/version.rb +2 -2
  236. data/lib/mongoid/versioning.rb +25 -26
  237. data/lib/rack/mongoid/middleware/identity_map.rb +3 -3
  238. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -1
  239. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +59 -19
  240. data/lib/rails/generators/mongoid/model/model_generator.rb +7 -7
  241. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +2 -2
  242. data/lib/rails/generators/mongoid/observer/observer_generator.rb +4 -4
  243. data/lib/rails/generators/mongoid_generator.rb +5 -5
  244. data/lib/rails/mongoid.rb +69 -25
  245. metadata +110 -137
  246. checksums.yaml +0 -7
  247. data/lib/config/locales/bg.yml +0 -61
  248. data/lib/config/locales/de.yml +0 -61
  249. data/lib/config/locales/en-GB.yml +0 -64
  250. data/lib/config/locales/es.yml +0 -59
  251. data/lib/config/locales/fr.yml +0 -62
  252. data/lib/config/locales/hi.yml +0 -53
  253. data/lib/config/locales/hu.yml +0 -64
  254. data/lib/config/locales/id.yml +0 -62
  255. data/lib/config/locales/it.yml +0 -59
  256. data/lib/config/locales/ja.yml +0 -57
  257. data/lib/config/locales/kr.yml +0 -54
  258. data/lib/config/locales/nl.yml +0 -61
  259. data/lib/config/locales/pl.yml +0 -59
  260. data/lib/config/locales/pt-BR.yml +0 -60
  261. data/lib/config/locales/pt.yml +0 -60
  262. data/lib/config/locales/ro.yml +0 -66
  263. data/lib/config/locales/ru.yml +0 -61
  264. data/lib/config/locales/sv.yml +0 -60
  265. data/lib/config/locales/vi.yml +0 -62
  266. data/lib/config/locales/zh-CN.yml +0 -53
  267. data/lib/mongoid/collection.rb +0 -157
  268. data/lib/mongoid/collections.rb +0 -120
  269. data/lib/mongoid/collections/master.rb +0 -45
  270. data/lib/mongoid/collections/operations.rb +0 -44
  271. data/lib/mongoid/config/database.rb +0 -181
  272. data/lib/mongoid/config/replset_database.rb +0 -80
  273. data/lib/mongoid/contexts.rb +0 -25
  274. data/lib/mongoid/contexts/enumerable.rb +0 -313
  275. data/lib/mongoid/contexts/enumerable/sort.rb +0 -43
  276. data/lib/mongoid/contexts/mongo.rb +0 -487
  277. data/lib/mongoid/criterion/builder.rb +0 -34
  278. data/lib/mongoid/criterion/complex.rb +0 -84
  279. data/lib/mongoid/criterion/creational.rb +0 -34
  280. data/lib/mongoid/criterion/exclusion.rb +0 -110
  281. data/lib/mongoid/criterion/inclusion.rb +0 -290
  282. data/lib/mongoid/criterion/optional.rb +0 -259
  283. data/lib/mongoid/criterion/selector.rb +0 -177
  284. data/lib/mongoid/cursor.rb +0 -88
  285. data/lib/mongoid/default_scope.rb +0 -36
  286. data/lib/mongoid/errors/invalid_type.rb +0 -25
  287. data/lib/mongoid/extensions/array/deep_copy.rb +0 -25
  288. data/lib/mongoid/extensions/array/deletion.rb +0 -29
  289. data/lib/mongoid/extensions/false_class/equality.rb +0 -26
  290. data/lib/mongoid/extensions/hash/criteria_helpers.rb +0 -47
  291. data/lib/mongoid/extensions/hash/deep_copy.rb +0 -25
  292. data/lib/mongoid/extensions/hash/scoping.rb +0 -25
  293. data/lib/mongoid/extensions/integer/checks.rb +0 -23
  294. data/lib/mongoid/extensions/nil/collectionization.rb +0 -23
  295. data/lib/mongoid/extensions/object/checks.rb +0 -29
  296. data/lib/mongoid/extensions/object/deep_copy.rb +0 -21
  297. data/lib/mongoid/extensions/object/reflections.rb +0 -48
  298. data/lib/mongoid/extensions/object/substitutable.rb +0 -15
  299. data/lib/mongoid/extensions/object/yoda.rb +0 -44
  300. data/lib/mongoid/extensions/object_id/conversions.rb +0 -60
  301. data/lib/mongoid/extensions/proc/scoping.rb +0 -25
  302. data/lib/mongoid/extensions/string/checks.rb +0 -36
  303. data/lib/mongoid/extensions/string/conversions.rb +0 -22
  304. data/lib/mongoid/extensions/string/inflections.rb +0 -118
  305. data/lib/mongoid/extensions/symbol/checks.rb +0 -23
  306. data/lib/mongoid/extensions/symbol/inflections.rb +0 -67
  307. data/lib/mongoid/extensions/true_class/equality.rb +0 -26
  308. data/lib/mongoid/extras.rb +0 -31
  309. data/lib/mongoid/fields/internal/array.rb +0 -77
  310. data/lib/mongoid/fields/internal/big_decimal.rb +0 -63
  311. data/lib/mongoid/fields/internal/bignum.rb +0 -10
  312. data/lib/mongoid/fields/internal/binary.rb +0 -11
  313. data/lib/mongoid/fields/internal/boolean.rb +0 -58
  314. data/lib/mongoid/fields/internal/date.rb +0 -51
  315. data/lib/mongoid/fields/internal/date_time.rb +0 -28
  316. data/lib/mongoid/fields/internal/false_class.rb +0 -10
  317. data/lib/mongoid/fields/internal/fixnum.rb +0 -10
  318. data/lib/mongoid/fields/internal/float.rb +0 -47
  319. data/lib/mongoid/fields/internal/foreign_keys/array.rb +0 -88
  320. data/lib/mongoid/fields/internal/foreign_keys/object.rb +0 -56
  321. data/lib/mongoid/fields/internal/hash.rb +0 -11
  322. data/lib/mongoid/fields/internal/integer.rb +0 -59
  323. data/lib/mongoid/fields/internal/localized.rb +0 -62
  324. data/lib/mongoid/fields/internal/nil_class.rb +0 -53
  325. data/lib/mongoid/fields/internal/object.rb +0 -11
  326. data/lib/mongoid/fields/internal/object_id.rb +0 -46
  327. data/lib/mongoid/fields/internal/range.rb +0 -61
  328. data/lib/mongoid/fields/internal/set.rb +0 -57
  329. data/lib/mongoid/fields/internal/string.rb +0 -42
  330. data/lib/mongoid/fields/internal/symbol.rb +0 -43
  331. data/lib/mongoid/fields/internal/time.rb +0 -23
  332. data/lib/mongoid/fields/internal/time_with_zone.rb +0 -23
  333. data/lib/mongoid/fields/internal/timekeeping.rb +0 -122
  334. data/lib/mongoid/fields/internal/true_class.rb +0 -10
  335. data/lib/mongoid/fields/mappings.rb +0 -42
  336. data/lib/mongoid/fields/serializable.rb +0 -270
  337. data/lib/mongoid/identity.rb +0 -92
  338. data/lib/mongoid/keys.rb +0 -144
  339. data/lib/mongoid/logger.rb +0 -45
  340. data/lib/mongoid/multi_database.rb +0 -36
  341. data/lib/mongoid/named_scope.rb +0 -166
  342. data/lib/mongoid/relations/embedded/atomic.rb +0 -89
  343. data/lib/mongoid/relations/embedded/atomic/operation.rb +0 -63
  344. data/lib/mongoid/relations/embedded/atomic/pull.rb +0 -65
  345. data/lib/mongoid/relations/embedded/atomic/push_all.rb +0 -59
  346. data/lib/mongoid/relations/embedded/atomic/set.rb +0 -61
  347. data/lib/mongoid/relations/embedded/atomic/unset.rb +0 -41
  348. data/lib/mongoid/relations/referenced/batch.rb +0 -73
  349. data/lib/mongoid/relations/referenced/batch/insert.rb +0 -57
  350. data/lib/mongoid/safety.rb +0 -105
  351. data/lib/mongoid/scope.rb +0 -31
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
3
- module Relations #:nodoc:
4
- module Referenced #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
+ module Referenced
5
5
 
6
6
  # This class defines the behaviour for all relations that are a
7
7
  # many-to-many between documents in different collections.
@@ -25,29 +25,51 @@ module Mongoid # :nodoc:
25
25
  #
26
26
  # @since 2.0.0.beta.1
27
27
  def <<(*args)
28
- batched do
29
- [].tap do |ids|
30
- args.flatten.each do |doc|
31
- next unless doc
32
- append(doc)
33
- if persistable? || _creating?
34
- ids.push(doc.id)
35
- doc.save
36
- else
37
- base.send(metadata.foreign_key).push(doc.id)
38
- base.synced[metadata.foreign_key] = false
39
- end
40
- end
28
+ docs = args.flatten
29
+ return concat(docs) if docs.size > 1
30
+ if doc = docs.first
31
+ if !target.include?(doc)
32
+ append(doc)
33
+ base.push(foreign_key, doc.id)
41
34
  if persistable? || _creating?
42
- base.push_all(metadata.foreign_key, ids)
43
- base.synced[metadata.foreign_key] = false
35
+ doc.save
44
36
  end
45
37
  end
46
38
  end
39
+ unsynced(base, foreign_key) and self
47
40
  end
48
- alias :concat :<<
49
41
  alias :push :<<
50
42
 
43
+ # Appends an array of documents to the relation. Performs a batch
44
+ # insert of the documents instead of persisting one at a time.
45
+ #
46
+ # @example Concat with other documents.
47
+ # person.posts.concat([ post_one, post_two ])
48
+ #
49
+ # @param [ Array<Document> ] documents The docs to add.
50
+ #
51
+ # @return [ Array<Document> ] The documents.
52
+ #
53
+ # @since 2.4.0
54
+ def concat(documents)
55
+ ids, inserts = [], []
56
+ documents.each do |doc|
57
+ next if doc.nil? || target.include?(doc)
58
+ append(doc)
59
+ if persistable? || _creating?
60
+ ids.push(doc.id)
61
+ save_or_delay(doc, inserts)
62
+ else
63
+ base.send(foreign_key).push(doc.id) and unsynced(base, foreign_key)
64
+ end
65
+ end
66
+ if persistable? || _creating?
67
+ base.push_all(foreign_key, ids)
68
+ end
69
+ persist_delayed(inserts)
70
+ self
71
+ end
72
+
51
73
  # Build a new document from the attributes and append it to this
52
74
  # relation without saving.
53
75
  #
@@ -72,13 +94,13 @@ module Mongoid # :nodoc:
72
94
  options, type = {}, options
73
95
  end
74
96
 
75
- Factory.build(type || klass, attributes, options).tap do |doc|
76
- base.send(metadata.foreign_key).push(doc.id)
77
- append(doc)
78
- doc.apply_proc_defaults
79
- doc.synced[metadata.inverse_foreign_key] = false
80
- yield(doc) if block_given?
81
- end
97
+ doc = Factory.build(type || klass, attributes, options)
98
+ base.send(foreign_key).push(doc.id)
99
+ append(doc)
100
+ doc.apply_post_processed_defaults
101
+ unsynced(doc, inverse_foreign_key)
102
+ yield(doc) if block_given?
103
+ doc
82
104
  end
83
105
  alias :new :build
84
106
 
@@ -95,12 +117,12 @@ module Mongoid # :nodoc:
95
117
  #
96
118
  # @since 2.1.0
97
119
  def delete(document)
98
- super.tap do |doc|
99
- if doc && persistable?
100
- base.pull(metadata.foreign_key, doc.id)
101
- base.synced[metadata.foreign_key] = false
102
- end
120
+ doc = super
121
+ if doc && persistable?
122
+ base.pull(foreign_key, doc.id)
123
+ unsynced(base, foreign_key)
103
124
  end
125
+ doc
104
126
  end
105
127
 
106
128
  # Removes all associations between the base document and the target
@@ -113,12 +135,12 @@ module Mongoid # :nodoc:
113
135
  # @since 2.0.0.rc.1
114
136
  def nullify
115
137
  unless metadata.forced_nil_inverse?
116
- criteria.pull(metadata.inverse_foreign_key, base.id)
138
+ criteria.pull(inverse_foreign_key, base.id)
117
139
  end
118
140
  if persistable?
119
141
  base.set(
120
- metadata.foreign_key,
121
- base.send(metadata.foreign_key).clear
142
+ foreign_key,
143
+ base.send(foreign_key).clear
122
144
  )
123
145
  end
124
146
  target.clear do |doc|
@@ -142,10 +164,9 @@ module Mongoid # :nodoc:
142
164
  #
143
165
  # @since 2.0.0.rc.1
144
166
  def substitute(replacement)
145
- tap do |proxy|
146
- proxy.purge
147
- proxy.push(replacement.compact.uniq) unless replacement.blank?
148
- end
167
+ purge
168
+ push(replacement.compact.uniq) unless replacement.blank?
169
+ self
149
170
  end
150
171
 
151
172
  # Get a criteria for the documents without the default scoping
@@ -158,7 +179,7 @@ module Mongoid # :nodoc:
158
179
  #
159
180
  # @since 2.4.0
160
181
  def unscoped
161
- klass.unscoped.any_in(:_id => base.send(metadata.foreign_key))
182
+ klass.unscoped.any_in(_id: base.send(foreign_key))
162
183
  end
163
184
 
164
185
  private
@@ -198,7 +219,25 @@ module Mongoid # :nodoc:
198
219
  #
199
220
  # @return [ Criteria ] A new criteria.
200
221
  def criteria
201
- ManyToMany.criteria(metadata, base.send(metadata.foreign_key))
222
+ ManyToMany.criteria(metadata, base.send(foreign_key))
223
+ end
224
+
225
+ # Flag the base as unsynced with respect to the foreign key.
226
+ #
227
+ # @api private
228
+ #
229
+ # @example Flag as unsynced.
230
+ # relation.unsynced(doc, :preference_ids)
231
+ #
232
+ # @param [ Document ] doc The document to flag.
233
+ # @param [ Symbol ] key The key to flag on the document.
234
+ #
235
+ # @return [ true ] true.
236
+ #
237
+ # @since 3.0.0
238
+ def unsynced(doc, key)
239
+ doc.synced[key] = false
240
+ true
202
241
  end
203
242
 
204
243
  class << self
@@ -235,7 +274,7 @@ module Mongoid # :nodoc:
235
274
  #
236
275
  # @since 2.1.0
237
276
  def criteria(metadata, object, type = nil)
238
- metadata.klass.any_in(:_id => object)
277
+ metadata.klass.all_of(_id: { "$in" => object })
239
278
  end
240
279
 
241
280
  # Get the criteria that is used to eager load a relation of this
@@ -245,13 +284,15 @@ module Mongoid # :nodoc:
245
284
  # Proxy.eager_load(metadata, criteria)
246
285
  #
247
286
  # @param [ Metadata ] metadata The relation metadata.
248
- # @param [ Criteria ] criteria The criteria being used.
287
+ # @param [ Array<Object> ] ids The ids of the documents to load.
249
288
  #
250
289
  # @return [ Criteria ] The criteria to eager load the relation.
251
290
  #
252
291
  # @since 2.2.0
253
- def eager_load(metadata, criteria)
254
- raise Errors::EagerLoad.new(metadata.name)
292
+ def eager_load(metadata, ids)
293
+ metadata.klass.any_in(_id: ids).each do |doc|
294
+ IdentityMap.set(doc)
295
+ end
255
296
  end
256
297
 
257
298
  # Returns true if the relation is an embedded one. In this case
@@ -267,6 +308,20 @@ module Mongoid # :nodoc:
267
308
  false
268
309
  end
269
310
 
311
+ # Get the foreign key for the provided name.
312
+ #
313
+ # @example Get the foreign key.
314
+ # Referenced::ManyToMany.foreign_key(:person)
315
+ #
316
+ # @param [ Symbol ] name The name.
317
+ #
318
+ # @return [ String ] The foreign key.
319
+ #
320
+ # @since 3.0.0
321
+ def foreign_key(name)
322
+ "#{name.to_s.singularize}#{foreign_key_suffix}"
323
+ end
324
+
270
325
  # Get the default value for the foreign key.
271
326
  #
272
327
  # @example Get the default.
@@ -297,9 +352,9 @@ module Mongoid # :nodoc:
297
352
  # @example Get the macro.
298
353
  # Referenced::ManyToMany.macro
299
354
  #
300
- # @return [ Symbol ] :references_and_referenced_in_many
355
+ # @return [ Symbol ] :has_and_belongs_to_many
301
356
  def macro
302
- :references_and_referenced_in_many
357
+ :has_and_belongs_to_many
303
358
  end
304
359
 
305
360
  # Return the nested builder that is responsible for generating the documents
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
3
- module Relations #:nodoc:
4
- module Referenced #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
+ module Referenced
5
5
 
6
6
  # This class defines the behaviour for all relations that are a
7
7
  # one-to-one between documents in different collections.
@@ -59,8 +59,7 @@ module Mongoid # :nodoc:
59
59
  save if persisted?
60
60
  end
61
61
  end
62
- return nil unless replacement
63
- One.new(base, replacement, metadata)
62
+ One.new(base, replacement, metadata) if replacement
64
63
  end
65
64
 
66
65
  private
@@ -122,7 +121,18 @@ module Mongoid # :nodoc:
122
121
  #
123
122
  # @since 2.1.0
124
123
  def criteria(metadata, object, type = nil)
125
- metadata.klass.where(metadata.foreign_key => object)
124
+ crit = metadata.klass.where(metadata.foreign_key => object)
125
+
126
+ if metadata.polymorphic?
127
+ crit = crit.where(metadata.type => type.name)
128
+ end
129
+
130
+ inverse_metadata = metadata.inverse_metadata(metadata.klass)
131
+ if inverse_metadata.inverse_of_field
132
+ crit = crit.any_in(inverse_metadata.inverse_of_field => [metadata.name, nil])
133
+ end
134
+
135
+ crit
126
136
  end
127
137
 
128
138
  # Get the criteria that is used to eager load a relation of this
@@ -138,10 +148,7 @@ module Mongoid # :nodoc:
138
148
  #
139
149
  # @since 2.2.0
140
150
  def eager_load(metadata, ids)
141
- klass, foreign_key = metadata.klass, metadata.foreign_key
142
- klass.any_in(foreign_key => ids).each do |doc|
143
- IdentityMap.set_one(doc, foreign_key => doc.send(foreign_key))
144
- end
151
+ eager_load_ids(metadata, ids) { |doc, key| IdentityMap.set_one(doc, key) }
145
152
  end
146
153
 
147
154
  # Returns true if the relation is an embedded one. In this case
@@ -157,6 +164,20 @@ module Mongoid # :nodoc:
157
164
  false
158
165
  end
159
166
 
167
+ # Get the foreign key for the provided name.
168
+ #
169
+ # @example Get the foreign key.
170
+ # Referenced::One.foreign_key(:person)
171
+ #
172
+ # @param [ Symbol ] name The name.
173
+ #
174
+ # @return [ String ] The foreign key.
175
+ #
176
+ # @since 3.0.0
177
+ def foreign_key(name)
178
+ "#{name}#{foreign_key_suffix}"
179
+ end
180
+
160
181
  # Get the default value for the foreign key.
161
182
  #
162
183
  # @example Get the default.
@@ -187,9 +208,9 @@ module Mongoid # :nodoc:
187
208
  # @example Get the macro.
188
209
  # Referenced::One.macro
189
210
  #
190
- # @return [ Symbol ] :references_one.
211
+ # @return [ Symbol ] :has_one.
191
212
  def macro
192
- :references_one
213
+ :has_one
193
214
  end
194
215
 
195
216
  # Return the nested builder that is responsible for generating the documents
@@ -254,7 +275,7 @@ module Mongoid # :nodoc:
254
275
  #
255
276
  # @since 2.1.0
256
277
  def valid_options
257
- [ :as, :autosave, :dependent, :foreign_key ]
278
+ [ :as, :autobuild, :autosave, :dependent, :foreign_key ]
258
279
  end
259
280
 
260
281
  # Get the default validation setting for the relation. Determines if
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
3
- module Relations #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
4
 
5
5
  # The reflections module provides convenience methods that can retrieve
6
6
  # useful information about associations.
@@ -31,7 +31,7 @@ module Mongoid # :nodoc:
31
31
  self.class.reflect_on_all_associations(*macros)
32
32
  end
33
33
 
34
- module ClassMethods #:nodoc
34
+ module ClassMethods
35
35
 
36
36
  # Returns the relation metadata for the supplied name.
37
37
  #
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
3
- module Relations #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
4
 
5
5
  # This module handles the behaviour for synchronizing foreign keys between
6
6
  # both sides of a many to many relations.
@@ -36,8 +36,6 @@ module Mongoid # :nodoc:
36
36
 
37
37
  # Has the document been synced for the foreign key?
38
38
  #
39
- # @todo Change the sync to be key based.
40
- #
41
39
  # @example Has the document been synced?
42
40
  # document.synced?
43
41
  #
@@ -61,7 +59,7 @@ module Mongoid # :nodoc:
61
59
  #
62
60
  # @since 2.2.1
63
61
  def remove_inverse_keys(meta)
64
- meta.criteria(send(meta.foreign_key)).pull(meta.inverse_foreign_key, id)
62
+ meta.criteria(send(meta.foreign_key), self.class).pull(meta.inverse_foreign_key, id)
65
63
  end
66
64
 
67
65
  # Update the inverse keys for the relation.
@@ -91,15 +89,15 @@ module Mongoid # :nodoc:
91
89
  end
92
90
 
93
91
  unless adds.empty?
94
- meta.criteria(adds).add_to_set(meta.inverse_foreign_key, id)
92
+ meta.criteria(adds, self.class).add_to_set(meta.inverse_foreign_key, id)
95
93
  end
96
94
  unless subs.empty?
97
- meta.criteria(subs).pull(meta.inverse_foreign_key, id)
95
+ meta.criteria(subs, self.class).pull(meta.inverse_foreign_key, id)
98
96
  end
99
97
  end
100
98
  end
101
99
 
102
- module ClassMethods #:nodoc:
100
+ module ClassMethods
103
101
 
104
102
  # Set up the syncing of many to many foreign keys.
105
103
  #
@@ -133,15 +131,14 @@ module Mongoid # :nodoc:
133
131
  #
134
132
  # @since 2.1.0
135
133
  def synced_save(metadata)
136
- tap do
137
- set_callback(
138
- :save,
139
- :after,
140
- :if => lambda { |doc| doc.syncable?(metadata) }
141
- ) do |doc|
142
- doc.update_inverse_keys(metadata)
143
- end
134
+ set_callback(
135
+ :save,
136
+ :after,
137
+ if: ->(doc){ doc.syncable?(metadata) }
138
+ ) do |doc|
139
+ doc.update_inverse_keys(metadata)
144
140
  end
141
+ self
145
142
  end
146
143
 
147
144
  # Set up the sync of inverse keys that needs to happen on a destroy.
@@ -155,14 +152,13 @@ module Mongoid # :nodoc:
155
152
  #
156
153
  # @since 2.2.1
157
154
  def synced_destroy(metadata)
158
- tap do
159
- set_callback(
160
- :destroy,
161
- :after
162
- ) do |doc|
163
- doc.remove_inverse_keys(metadata)
164
- end
155
+ set_callback(
156
+ :destroy,
157
+ :after
158
+ ) do |doc|
159
+ doc.remove_inverse_keys(metadata)
165
160
  end
161
+ self
166
162
  end
167
163
  end
168
164
  end
@@ -1,22 +1,22 @@
1
1
  # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Relations #:nodoc:
4
- module Targets #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
+ module Targets
5
5
 
6
6
  # This class is the wrapper for all relational associations that have a
7
- # target that can be a criteria or array of loaded documents. This
7
+ # target that can be a criteria or array of _loaded documents. This
8
8
  # handles both cases or a combination of the two.
9
9
  class Enumerable
10
10
  include ::Enumerable
11
11
 
12
12
  # The three main instance variables are collections of documents.
13
13
  #
14
- # @attribute [rw] added Documents that have been appended.
15
- # @attribute [rw] loaded Persisted documents that have been loaded.
16
- # @attribute [rw] unloaded A criteria representing persisted docs.
17
- attr_accessor :added, :loaded, :unloaded
14
+ # @attribute [rw] _added Documents that have been appended.
15
+ # @attribute [rw] _loaded Persisted documents that have been _loaded.
16
+ # @attribute [rw] _unloaded A criteria representing persisted docs.
17
+ attr_accessor :_added, :_loaded, :_unloaded
18
18
 
19
- delegate :===, :is_a?, :kind_of?, :to => :added
19
+ delegate :===, :is_a?, :kind_of?, to: []
20
20
 
21
21
  # Check if the enumerable is equal to the other object.
22
22
  #
@@ -44,7 +44,8 @@ module Mongoid #:nodoc:
44
44
  #
45
45
  # @since 2.1.0
46
46
  def <<(document)
47
- added.push(document)
47
+ _added[document.id] = document
48
+ self
48
49
  end
49
50
  alias :push :<<
50
51
 
@@ -59,14 +60,14 @@ module Mongoid #:nodoc:
59
60
  # doc.unbind
60
61
  # end
61
62
  #
62
- # @return [ Array<Document> ] The cleared out added docs.
63
+ # @return [ Array<Document> ] The cleared out _added docs.
63
64
  #
64
65
  # @since 2.1.0
65
66
  def clear
66
67
  if block_given?
67
68
  in_memory { |doc| yield(doc) }
68
69
  end
69
- loaded.clear and added.clear
70
+ _loaded.clear and _added.clear
70
71
  end
71
72
 
72
73
  # Clones each document in the enumerable.
@@ -94,15 +95,15 @@ module Mongoid #:nodoc:
94
95
  #
95
96
  # @since 2.1.0
96
97
  def delete(document)
97
- (loaded.delete(document) || added.delete(document)).tap do |doc|
98
- unless doc
99
- if unloaded && unloaded.where(:_id => document.id).exists?
100
- yield(document) if block_given?
101
- return document
102
- end
98
+ doc = (_loaded.delete(document.id) || _added.delete(document.id))
99
+ unless doc
100
+ if _unloaded && _unloaded.where(_id: document.id).exists?
101
+ yield(document) if block_given?
102
+ return document
103
103
  end
104
- yield(doc) if block_given?
105
104
  end
105
+ yield(doc) if block_given?
106
+ doc
106
107
  end
107
108
 
108
109
  # Deletes every document in the enumerable for where the block returns
@@ -120,50 +121,52 @@ module Mongoid #:nodoc:
120
121
  # @since 2.1.0
121
122
  def delete_if(&block)
122
123
  load_all!
123
- tap do
124
- loaded.delete_if(&block)
125
- added.delete_if(&block)
124
+ deleted = in_memory.select(&block)
125
+ deleted.each do |doc|
126
+ _loaded.delete(doc.id)
127
+ _added.delete(doc.id)
126
128
  end
129
+ self
127
130
  end
128
131
 
129
132
  # Iterating over this enumerable has to handle a few different
130
133
  # scenarios.
131
134
  #
132
- # If the enumerable has its criteria loaded into memory then it yields
133
- # to all the loaded docs and all the added docs.
135
+ # If the enumerable has its criteria _loaded into memory then it yields
136
+ # to all the _loaded docs and all the _added docs.
134
137
  #
135
- # If the enumerable has not loaded the criteria then it iterates over
138
+ # If the enumerable has not _loaded the criteria then it iterates over
136
139
  # the cursor while loading the documents and then iterates over the
137
- # added docs.
140
+ # _added docs.
138
141
  #
139
142
  # @example Iterate over the enumerable.
140
143
  # enumerable.each do |doc|
141
144
  # puts doc
142
145
  # end
143
146
  #
144
- # @return [ true ] That the enumerable is now loaded.
147
+ # @return [ true ] That the enumerable is now _loaded.
145
148
  #
146
149
  # @since 2.1.0
147
150
  def each
148
- if loaded?
149
- loaded.each do |doc|
151
+ if _loaded?
152
+ _loaded.each_pair do |id, doc|
150
153
  yield(doc)
151
154
  end
152
155
  else
153
- unloaded.each do |doc|
154
- document = added.delete_one(doc) || loaded.delete_one(doc) || doc
156
+ _unloaded.each do |doc|
157
+ document = _added.delete(doc.id) || _loaded.delete(doc.id) || doc
155
158
  yield(document)
156
- loaded.push(document)
159
+ _loaded[document.id] = document
157
160
  end
158
161
  end
159
- added.each do |doc|
162
+ _added.each_pair do |id, doc|
160
163
  yield(doc)
161
164
  end
162
165
  @executed = true
163
166
  end
164
167
 
165
168
  # Is the enumerable empty? Will determine if the count is zero based on
166
- # whether or not it is loaded.
169
+ # whether or not it is _loaded.
167
170
  #
168
171
  # @example Is the enumerable empty?
169
172
  # enumerable.empty?
@@ -172,10 +175,10 @@ module Mongoid #:nodoc:
172
175
  #
173
176
  # @since 2.1.0
174
177
  def empty?
175
- if loaded?
178
+ if _loaded?
176
179
  in_memory.count == 0
177
180
  else
178
- unloaded.count + added.count == 0
181
+ _unloaded.count + _added.count == 0
179
182
  end
180
183
  end
181
184
 
@@ -189,7 +192,7 @@ module Mongoid #:nodoc:
189
192
  #
190
193
  # @since 2.1.0
191
194
  def first
192
- added.first || (loaded? ? loaded.first : unloaded.first)
195
+ matching_document(:first)
193
196
  end
194
197
 
195
198
  # Initialize the new enumerable either with a criteria or an array.
@@ -205,12 +208,31 @@ module Mongoid #:nodoc:
205
208
  # @since 2.1.0
206
209
  def initialize(target)
207
210
  if target.is_a?(Criteria)
208
- @added, @loaded, @unloaded = [], [], target
211
+ @_added, @executed, @_loaded, @_unloaded = {}, false, {}, target
209
212
  else
210
- @added, @executed, @loaded = [], true, target
213
+ @_added, @executed = {}, true
214
+ @_loaded = target.inject({}) do |_target, doc|
215
+ _target[doc.id] = doc
216
+ _target
217
+ end
211
218
  end
212
219
  end
213
220
 
221
+ # Does the target include the provided document?
222
+ #
223
+ # @example Does the target include the document?
224
+ # enumerable.include?(document)
225
+ #
226
+ # @param [ Document ] doc The document to check.
227
+ #
228
+ # @return [ true, false ] If the document is in the target.
229
+ #
230
+ # @since 3.0.0
231
+ def include?(doc)
232
+ return super unless _unloaded
233
+ _unloaded.where(_id: doc.id).exists? || _added.has_key?(doc.id)
234
+ end
235
+
214
236
  # Inspection will just inspect the entries for nice array-style
215
237
  # printing.
216
238
  #
@@ -224,8 +246,8 @@ module Mongoid #:nodoc:
224
246
  entries.inspect
225
247
  end
226
248
 
227
- # Return all the documents in the enumerable that have been loaded or
228
- # added.
249
+ # Return all the documents in the enumerable that have been _loaded or
250
+ # _added.
229
251
  #
230
252
  # @note When passed a block it yields to each document.
231
253
  #
@@ -236,9 +258,9 @@ module Mongoid #:nodoc:
236
258
  #
237
259
  # @since 2.1.0
238
260
  def in_memory
239
- (loaded + added).tap do |docs|
240
- docs.each { |doc| yield(doc) } if block_given?
241
- end
261
+ docs = (_loaded.values + _added.values)
262
+ docs.each { |doc| yield(doc) } if block_given?
263
+ docs
242
264
  end
243
265
 
244
266
  # Get the last document in the enumerable. Will check the new
@@ -251,7 +273,7 @@ module Mongoid #:nodoc:
251
273
  #
252
274
  # @since 2.1.0
253
275
  def last
254
- added.last || (loaded? ? loaded.last : unloaded.last)
276
+ matching_document(:last)
255
277
  end
256
278
 
257
279
  # Loads all the documents in the enumerable from the database.
@@ -259,21 +281,21 @@ module Mongoid #:nodoc:
259
281
  # @example Load all the documents.
260
282
  # enumerable.load_all!
261
283
  #
262
- # @return [ true ] That the enumerable is loaded.
284
+ # @return [ true ] That the enumerable is _loaded.
263
285
  #
264
286
  # @since 2.1.0
265
287
  alias :load_all! :entries
266
288
 
267
- # Has the enumerable been loaded? This will be true if the criteria has
289
+ # Has the enumerable been _loaded? This will be true if the criteria has
268
290
  # been executed or we manually load the entire thing.
269
291
  #
270
- # @example Is the enumerable loaded?
271
- # enumerable.loaded?
292
+ # @example Is the enumerable _loaded?
293
+ # enumerable._loaded?
272
294
  #
273
- # @return [ true, false ] If the enumerable has been loaded.
295
+ # @return [ true, false ] If the enumerable has been _loaded.
274
296
  #
275
297
  # @since 2.1.0
276
- def loaded?
298
+ def _loaded?
277
299
  !!@executed
278
300
  end
279
301
 
@@ -286,7 +308,7 @@ module Mongoid #:nodoc:
286
308
  #
287
309
  # @since 2.1.0
288
310
  def reset
289
- loaded.clear and added.clear
311
+ _loaded.clear and _added.clear
290
312
  @executed = false
291
313
  end
292
314
 
@@ -316,11 +338,11 @@ module Mongoid #:nodoc:
316
338
  #
317
339
  # @since 2.1.0
318
340
  def size
319
- count = (unloaded ? unloaded.count : loaded.count)
341
+ count = (_unloaded ? _unloaded.count : _loaded.count)
320
342
  if count.zero?
321
- count + added.count
343
+ count + _added.count
322
344
  else
323
- count + added.count{ |d| d.new_record? }
345
+ count + _added.values.count{ |d| d.new_record? }
324
346
  end
325
347
  end
326
348
  alias :length :size
@@ -332,7 +354,7 @@ module Mongoid #:nodoc:
332
354
  #
333
355
  # @param [ Hash ] options Optional parameters.
334
356
  #
335
- # @return [ String ] The entries all loaded as a string.
357
+ # @return [ String ] The entries all _loaded as a string.
336
358
  #
337
359
  # @since 2.2.0
338
360
  def to_json(options = {})
@@ -346,7 +368,7 @@ module Mongoid #:nodoc:
346
368
  #
347
369
  # @param [ Hash ] options Optional parameters.
348
370
  #
349
- # @return [ Hash ] The entries all loaded as a hash.
371
+ # @return [ Hash ] The entries all _loaded as a hash.
350
372
  #
351
373
  # @since 2.2.0
352
374
  def as_json(options = {})
@@ -372,6 +394,13 @@ module Mongoid #:nodoc:
372
394
  def method_missing(name, *args, &block)
373
395
  entries.send(name, *args, &block)
374
396
  end
397
+
398
+ def matching_document(location)
399
+ _loaded.try(:values).try(location) ||
400
+ _added[_unloaded.try(location).try(:id)] ||
401
+ _unloaded.try(location) ||
402
+ _added.values.try(location)
403
+ end
375
404
  end
376
405
  end
377
406
  end