mongoid 7.4.0 → 8.0.3

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 (391) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +52 -28
  5. data/lib/mongoid/association/accessors.rb +38 -9
  6. data/lib/mongoid/association/bindable.rb +50 -2
  7. data/lib/mongoid/association/builders.rb +4 -2
  8. data/lib/mongoid/association/constrainable.rb +0 -1
  9. data/lib/mongoid/association/eager_loadable.rb +29 -7
  10. data/lib/mongoid/association/embedded/batchable.rb +53 -13
  11. data/lib/mongoid/association/embedded/cyclic.rb +1 -1
  12. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  13. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -2
  14. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  15. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  16. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  17. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +50 -28
  18. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  19. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  20. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +23 -4
  21. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  22. data/lib/mongoid/association/macros.rb +22 -1
  23. data/lib/mongoid/association/many.rb +11 -7
  24. data/lib/mongoid/association/nested/many.rb +5 -4
  25. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  26. data/lib/mongoid/association/nested/one.rb +5 -5
  27. data/lib/mongoid/association/one.rb +2 -2
  28. data/lib/mongoid/association/options.rb +9 -9
  29. data/lib/mongoid/association/proxy.rb +14 -3
  30. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  31. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  32. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  33. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  34. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  35. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  36. data/lib/mongoid/association/referenced/eager.rb +2 -2
  37. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +66 -13
  38. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  39. data/lib/mongoid/association/referenced/has_many/enumerable.rb +20 -24
  40. data/lib/mongoid/association/referenced/has_many/proxy.rb +24 -18
  41. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  42. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  43. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  44. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  45. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  46. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  47. data/lib/mongoid/association/reflections.rb +2 -2
  48. data/lib/mongoid/association/relatable.rb +44 -10
  49. data/lib/mongoid/association.rb +5 -5
  50. data/lib/mongoid/atomic/modifiers.rb +2 -2
  51. data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
  52. data/lib/mongoid/attributes/dynamic.rb +3 -3
  53. data/lib/mongoid/attributes/nested.rb +5 -5
  54. data/lib/mongoid/attributes/processing.rb +10 -3
  55. data/lib/mongoid/attributes/projector.rb +1 -1
  56. data/lib/mongoid/attributes/readonly.rb +2 -2
  57. data/lib/mongoid/attributes.rb +43 -40
  58. data/lib/mongoid/cacheable.rb +2 -2
  59. data/lib/mongoid/changeable.rb +42 -7
  60. data/lib/mongoid/clients/options.rb +5 -1
  61. data/lib/mongoid/clients/sessions.rb +2 -14
  62. data/lib/mongoid/clients/validators/storage.rb +3 -3
  63. data/lib/mongoid/config/environment.rb +20 -4
  64. data/lib/mongoid/config/validators/client.rb +6 -6
  65. data/lib/mongoid/config.rb +32 -17
  66. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  67. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  68. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  69. data/lib/mongoid/contextual/atomic.rb +1 -1
  70. data/lib/mongoid/contextual/geo_near.rb +7 -7
  71. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  72. data/lib/mongoid/contextual/memory.rb +180 -21
  73. data/lib/mongoid/contextual/mongo.rb +237 -217
  74. data/lib/mongoid/contextual/none.rb +67 -5
  75. data/lib/mongoid/contextual/queryable.rb +1 -1
  76. data/lib/mongoid/contextual.rb +2 -2
  77. data/lib/mongoid/copyable.rb +32 -8
  78. data/lib/mongoid/criteria/findable.rb +7 -4
  79. data/lib/mongoid/criteria/includable.rb +24 -20
  80. data/lib/mongoid/criteria/marshalable.rb +10 -2
  81. data/lib/mongoid/criteria/permission.rb +1 -1
  82. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  83. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -13
  84. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  85. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  86. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  87. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  88. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -14
  89. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  90. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  91. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  92. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  93. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  94. data/lib/mongoid/criteria/queryable/extensions/string.rb +3 -3
  95. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -2
  96. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  97. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  98. data/lib/mongoid/criteria/queryable/key.rb +3 -3
  99. data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
  100. data/lib/mongoid/criteria/queryable/optional.rb +5 -11
  101. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  102. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  103. data/lib/mongoid/criteria/queryable/selectable.rb +31 -37
  104. data/lib/mongoid/criteria/queryable/selector.rb +92 -7
  105. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  106. data/lib/mongoid/criteria/queryable.rb +12 -7
  107. data/lib/mongoid/criteria/scopable.rb +2 -2
  108. data/lib/mongoid/criteria.rb +15 -35
  109. data/lib/mongoid/deprecable.rb +36 -0
  110. data/lib/mongoid/deprecation.rb +25 -0
  111. data/lib/mongoid/document.rb +98 -34
  112. data/lib/mongoid/equality.rb +12 -12
  113. data/lib/mongoid/errors/document_not_found.rb +33 -12
  114. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  115. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  116. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  117. data/lib/mongoid/errors/invalid_field.rb +6 -2
  118. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  119. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  120. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  121. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  122. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  123. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  124. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  125. data/lib/mongoid/errors/no_client_database.rb +1 -1
  126. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  127. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  128. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  129. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  130. data/lib/mongoid/errors.rb +2 -2
  131. data/lib/mongoid/extensions/array.rb +9 -7
  132. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  133. data/lib/mongoid/extensions/binary.rb +42 -0
  134. data/lib/mongoid/extensions/boolean.rb +8 -2
  135. data/lib/mongoid/extensions/date.rb +26 -20
  136. data/lib/mongoid/extensions/date_time.rb +1 -1
  137. data/lib/mongoid/extensions/false_class.rb +1 -1
  138. data/lib/mongoid/extensions/float.rb +7 -4
  139. data/lib/mongoid/extensions/hash.rb +13 -6
  140. data/lib/mongoid/extensions/integer.rb +7 -4
  141. data/lib/mongoid/extensions/module.rb +1 -1
  142. data/lib/mongoid/extensions/object.rb +8 -6
  143. data/lib/mongoid/extensions/range.rb +41 -10
  144. data/lib/mongoid/extensions/regexp.rb +11 -4
  145. data/lib/mongoid/extensions/set.rb +11 -4
  146. data/lib/mongoid/extensions/string.rb +11 -22
  147. data/lib/mongoid/extensions/symbol.rb +4 -15
  148. data/lib/mongoid/extensions/time.rb +27 -16
  149. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  150. data/lib/mongoid/extensions/true_class.rb +1 -1
  151. data/lib/mongoid/extensions.rb +1 -0
  152. data/lib/mongoid/factory.rb +42 -7
  153. data/lib/mongoid/fields/foreign_key.rb +11 -4
  154. data/lib/mongoid/fields/localized.rb +9 -4
  155. data/lib/mongoid/fields/standard.rb +7 -7
  156. data/lib/mongoid/fields/validators/macro.rb +3 -9
  157. data/lib/mongoid/fields.rb +201 -35
  158. data/lib/mongoid/findable.rb +34 -13
  159. data/lib/mongoid/indexable/specification.rb +2 -2
  160. data/lib/mongoid/indexable/validators/options.rb +6 -2
  161. data/lib/mongoid/interceptable.rb +73 -13
  162. data/lib/mongoid/matchable.rb +1 -1
  163. data/lib/mongoid/matcher.rb +12 -7
  164. data/lib/mongoid/persistable/creatable.rb +18 -9
  165. data/lib/mongoid/persistable/deletable.rb +1 -1
  166. data/lib/mongoid/persistable/destroyable.rb +1 -1
  167. data/lib/mongoid/persistable/savable.rb +2 -2
  168. data/lib/mongoid/persistable/unsettable.rb +1 -1
  169. data/lib/mongoid/persistable/updatable.rb +19 -12
  170. data/lib/mongoid/persistable/upsertable.rb +2 -2
  171. data/lib/mongoid/persistable.rb +3 -3
  172. data/lib/mongoid/persistence_context.rb +63 -10
  173. data/lib/mongoid/query_cache.rb +8 -260
  174. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  175. data/lib/mongoid/reloadable.rb +7 -3
  176. data/lib/mongoid/scopable.rb +26 -22
  177. data/lib/mongoid/selectable.rb +1 -2
  178. data/lib/mongoid/serializable.rb +10 -6
  179. data/lib/mongoid/stateful.rb +35 -9
  180. data/lib/mongoid/tasks/database.rb +0 -2
  181. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  182. data/lib/mongoid/threaded.rb +12 -12
  183. data/lib/mongoid/timestamps/created.rb +1 -1
  184. data/lib/mongoid/timestamps/updated.rb +2 -2
  185. data/lib/mongoid/touchable.rb +2 -3
  186. data/lib/mongoid/traversable.rb +8 -4
  187. data/lib/mongoid/validatable/localizable.rb +1 -1
  188. data/lib/mongoid/validatable/macros.rb +0 -2
  189. data/lib/mongoid/validatable/presence.rb +2 -2
  190. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  191. data/lib/mongoid/validatable.rb +6 -6
  192. data/lib/mongoid/version.rb +1 -1
  193. data/lib/mongoid/warnings.rb +28 -0
  194. data/lib/mongoid.rb +2 -0
  195. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +11 -5
  196. data/spec/config/mongoid.yml +16 -0
  197. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  198. data/spec/integration/app_spec.rb +28 -26
  199. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  200. data/spec/integration/associations/embedded_dirty_spec.rb +28 -0
  201. data/spec/integration/associations/embedded_spec.rb +15 -0
  202. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  203. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  204. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  205. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  206. data/spec/integration/associations/has_one_spec.rb +97 -1
  207. data/spec/integration/associations/scope_option_spec.rb +1 -1
  208. data/spec/integration/callbacks_models.rb +95 -1
  209. data/spec/integration/callbacks_spec.rb +226 -4
  210. data/spec/integration/criteria/range_spec.rb +95 -1
  211. data/spec/integration/discriminator_key_spec.rb +115 -76
  212. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  213. data/spec/integration/i18n_fallbacks_spec.rb +1 -17
  214. data/spec/integration/matcher_examples_spec.rb +20 -13
  215. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  216. data/spec/integration/matcher_operator_spec.rb +3 -5
  217. data/spec/integration/persistence/range_field_spec.rb +350 -0
  218. data/spec/lite_spec_helper.rb +1 -1
  219. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  220. data/spec/mongoid/association/depending_spec.rb +9 -9
  221. data/spec/mongoid/association/eager_spec.rb +2 -1
  222. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  223. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  224. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  225. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  226. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +219 -8
  227. data/spec/mongoid/association/embedded/embeds_many_models.rb +157 -0
  228. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  229. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  230. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  231. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  232. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  233. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  234. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  235. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  236. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  237. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  238. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +67 -4
  239. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  240. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  241. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  242. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +8 -8
  243. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +82 -13
  244. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  245. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  246. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  247. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  248. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  249. data/spec/mongoid/association/syncable_spec.rb +14 -0
  250. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  251. data/spec/mongoid/atomic_spec.rb +22 -0
  252. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  253. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  254. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  255. data/spec/mongoid/attributes_spec.rb +524 -27
  256. data/spec/mongoid/cacheable_spec.rb +3 -3
  257. data/spec/mongoid/changeable_spec.rb +130 -13
  258. data/spec/mongoid/clients/factory_spec.rb +34 -42
  259. data/spec/mongoid/clients/options_spec.rb +1 -0
  260. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  261. data/spec/mongoid/clients_spec.rb +57 -2
  262. data/spec/mongoid/config/environment_spec.rb +39 -1
  263. data/spec/mongoid/config_spec.rb +104 -13
  264. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  265. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  266. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  267. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  268. data/spec/mongoid/contextual/memory_spec.rb +1336 -69
  269. data/spec/mongoid/contextual/mongo_spec.rb +1105 -174
  270. data/spec/mongoid/contextual/none_spec.rb +38 -0
  271. data/spec/mongoid/copyable_spec.rb +451 -1
  272. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  273. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  274. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  275. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  276. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  277. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  278. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  279. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  280. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  281. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  282. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  283. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  284. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  285. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  286. data/spec/mongoid/criteria/queryable/selectable_spec.rb +289 -124
  287. data/spec/mongoid/criteria/queryable/selector_spec.rb +14 -2
  288. data/spec/mongoid/criteria_projection_spec.rb +0 -1
  289. data/spec/mongoid/criteria_spec.rb +475 -1199
  290. data/spec/mongoid/document_fields_spec.rb +173 -24
  291. data/spec/mongoid/document_spec.rb +32 -41
  292. data/spec/mongoid/equality_spec.rb +12 -12
  293. data/spec/mongoid/errors/document_not_found_spec.rb +76 -0
  294. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  295. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  296. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  297. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  298. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  299. data/spec/mongoid/extensions/array_spec.rb +16 -2
  300. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  301. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  302. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  303. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  304. data/spec/mongoid/extensions/date_spec.rb +71 -1
  305. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  306. data/spec/mongoid/extensions/float_spec.rb +53 -74
  307. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  308. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  309. data/spec/mongoid/extensions/range_spec.rb +255 -54
  310. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  311. data/spec/mongoid/extensions/set_spec.rb +106 -0
  312. data/spec/mongoid/extensions/string_spec.rb +53 -25
  313. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  314. data/spec/mongoid/extensions/time_spec.rb +634 -66
  315. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  316. data/spec/mongoid/factory_spec.rb +61 -1
  317. data/spec/mongoid/fields/localized_spec.rb +37 -12
  318. data/spec/mongoid/fields_spec.rb +321 -50
  319. data/spec/mongoid/findable_spec.rb +80 -15
  320. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  321. data/spec/mongoid/indexable_spec.rb +39 -20
  322. data/spec/mongoid/interceptable_spec.rb +584 -5
  323. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  324. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  325. data/spec/mongoid/mongoizable_spec.rb +285 -0
  326. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  327. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  328. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  329. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  330. data/spec/mongoid/persistence_context_spec.rb +50 -1
  331. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  332. data/spec/mongoid/query_cache_spec.rb +0 -154
  333. data/spec/mongoid/reloadable_spec.rb +35 -2
  334. data/spec/mongoid/scopable_spec.rb +54 -16
  335. data/spec/mongoid/shardable_spec.rb +14 -0
  336. data/spec/mongoid/stateful_spec.rb +28 -0
  337. data/spec/mongoid/timestamps_spec.rb +390 -0
  338. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  339. data/spec/mongoid/touchable_spec.rb +116 -0
  340. data/spec/mongoid/touchable_spec_models.rb +12 -8
  341. data/spec/mongoid/traversable_spec.rb +4 -11
  342. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  343. data/spec/mongoid/validatable/uniqueness_spec.rb +59 -31
  344. data/spec/mongoid/warnings_spec.rb +35 -0
  345. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  346. data/spec/rails/mongoid_spec.rb +4 -16
  347. data/spec/shared/lib/mrss/constraints.rb +8 -16
  348. data/spec/shared/lib/mrss/docker_runner.rb +23 -3
  349. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  350. data/spec/shared/lib/mrss/lite_constraints.rb +32 -1
  351. data/spec/shared/share/Dockerfile.erb +34 -48
  352. data/spec/shared/shlib/config.sh +27 -0
  353. data/spec/shared/shlib/server.sh +32 -19
  354. data/spec/shared/shlib/set_env.sh +37 -0
  355. data/spec/support/constraints.rb +24 -0
  356. data/spec/support/macros.rb +55 -0
  357. data/spec/support/models/augmentation.rb +12 -0
  358. data/spec/support/models/band.rb +3 -0
  359. data/spec/support/models/catalog.rb +24 -0
  360. data/spec/support/models/circus.rb +3 -0
  361. data/spec/support/models/code.rb +2 -0
  362. data/spec/support/models/fanatic.rb +8 -0
  363. data/spec/support/models/implant.rb +9 -0
  364. data/spec/support/models/label.rb +2 -0
  365. data/spec/support/models/membership.rb +1 -0
  366. data/spec/support/models/passport.rb +9 -0
  367. data/spec/support/models/person.rb +1 -0
  368. data/spec/support/models/player.rb +2 -0
  369. data/spec/support/models/powerup.rb +12 -0
  370. data/spec/support/models/registry.rb +1 -0
  371. data/spec/support/models/school.rb +14 -0
  372. data/spec/support/models/shield.rb +18 -0
  373. data/spec/support/models/student.rb +14 -0
  374. data/spec/support/models/weapon.rb +12 -0
  375. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  376. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  377. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  378. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  379. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  380. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  381. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  382. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  383. data/spec/support/schema_maps/schema_map_local.json +18 -0
  384. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  385. data/spec/support/spec_config.rb +4 -0
  386. data.tar.gz.sig +0 -0
  387. metadata +682 -619
  388. metadata.gz.sig +0 -0
  389. data/lib/mongoid/errors/eager_load.rb +0 -23
  390. data/lib/mongoid/errors/invalid_value.rb +0 -17
  391. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -44,39 +44,6 @@ describe Mongoid::Contextual::Mongo do
44
44
  end
45
45
  end
46
46
 
47
- describe "#cached?" do
48
-
49
- context "when the criteria is cached" do
50
-
51
- let(:criteria) do
52
- Band.all.cache
53
- end
54
-
55
- let(:context) do
56
- described_class.new(criteria)
57
- end
58
-
59
- it "returns true" do
60
- expect(context).to be_cached
61
- end
62
- end
63
-
64
- context "when the criteria is not cached" do
65
-
66
- let(:criteria) do
67
- Band.all
68
- end
69
-
70
- let(:context) do
71
- described_class.new(criteria)
72
- end
73
-
74
- it "returns false" do
75
- expect(context).to_not be_cached
76
- end
77
- end
78
- end
79
-
80
47
  describe "#count" do
81
48
 
82
49
  let!(:depeche) do
@@ -102,15 +69,17 @@ describe Mongoid::Contextual::Mongo do
102
69
  end
103
70
  end
104
71
 
105
- context "when context is cached" do
72
+ context "when the query cache is enabled" do
73
+ query_cache_enabled
106
74
 
107
75
  let(:context) do
108
- described_class.new(criteria.cache)
76
+ described_class.new(criteria)
109
77
  end
110
78
 
111
- it "returns the count cached value after first call" do
112
- expect(context.view).to receive(:count_documents).once.and_return(1)
113
- 2.times { expect(context.count).to eq(1) }
79
+ it "only executes the count query once" do
80
+ expect_query(1) do
81
+ 2.times { expect(context.count).to eq(1) }
82
+ end
114
83
  end
115
84
  end
116
85
 
@@ -217,16 +186,18 @@ describe Mongoid::Contextual::Mongo do
217
186
  end
218
187
  end
219
188
 
220
- context "when context is cached" do
189
+ context "when the query cache is enabled" do
190
+ query_cache_enabled
221
191
 
222
192
  let(:context) do
223
- described_class.new(criteria.cache)
193
+ described_class.new(criteria)
224
194
  end
225
195
 
226
- it "returns the count cached value after first call" do
227
- expect(context.view).to receive(:estimated_document_count).once.and_return(1)
228
- 2.times do
229
- context.estimated_count
196
+ it "the results are not cached" do
197
+ expect_query(2) do
198
+ 2.times do
199
+ context.estimated_count
200
+ end
230
201
  end
231
202
  end
232
203
  end
@@ -561,8 +532,22 @@ describe Mongoid::Contextual::Mongo do
561
532
  context "when legacy_pluck_distinct is set" do
562
533
  config_override :legacy_pluck_distinct, true
563
534
 
564
- it "returns the non-demongoized distinct field values" do
565
- expect(context.distinct(:sales).sort).to eq([ "1E2", "2E3" ])
535
+ context 'when storing BigDecimal as string' do
536
+ config_override :map_big_decimal_to_decimal128, false
537
+
538
+ it "returns the non-demongoized distinct field values" do
539
+ expect(context.distinct(:sales).sort).to eq([ "1E2", "2E3" ])
540
+ end
541
+ end
542
+
543
+ context 'when storing BigDecimal as decimal128' do
544
+ config_override :map_big_decimal_to_decimal128, true
545
+ min_bson_version '4.15.0'
546
+ max_bson_version '4.99.99'
547
+
548
+ it "returns the non-demongoized distinct field values" do
549
+ expect(context.distinct(:sales).sort).to eq([ BSON::Decimal128.new("1E2"), BSON::Decimal128.new("2E3") ])
550
+ end
566
551
  end
567
552
  end
568
553
 
@@ -675,7 +660,7 @@ describe Mongoid::Contextual::Mongo do
675
660
  end
676
661
 
677
662
  context 'when fallbacks are enabled with a locale list' do
678
- require_fallbacks
663
+ with_i18n_fallbacks
679
664
 
680
665
  around(:all) do |example|
681
666
  prev_fallbacks = I18n.fallbacks.dup
@@ -701,7 +686,7 @@ describe Mongoid::Contextual::Mongo do
701
686
 
702
687
  it "correctly uses the fallback" do
703
688
  I18n.locale = :en
704
- d = Dictionary.create!(description: 'english-text')
689
+ Dictionary.create!(description: 'english-text')
705
690
  I18n.locale = :he
706
691
  distinct.should == "english-text"
707
692
  end
@@ -782,9 +767,11 @@ describe Mongoid::Contextual::Mongo do
782
767
 
783
768
  context "when legacy_pluck_distinct is set" do
784
769
  config_override :legacy_pluck_distinct, true
770
+ config_override :map_big_decimal_to_decimal128, true
771
+ max_bson_version '4.99.99'
785
772
 
786
773
  it "returns the distinct matching fields" do
787
- expect(context.distinct("label.sales")).to eq([ "1E2" ])
774
+ expect(context.distinct("label.sales")).to eq([ BSON::Decimal128.new('1E+2') ])
788
775
  end
789
776
  end
790
777
 
@@ -797,6 +784,433 @@ describe Mongoid::Contextual::Mongo do
797
784
  end
798
785
  end
799
786
 
787
+ describe "#tally" do
788
+ let(:fans1) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
789
+ let(:fans2) { [ Fanatic.new(age:1), Fanatic.new(age:2) ] }
790
+ let(:fans3) { [ Fanatic.new(age:1), Fanatic.new(age:3) ] }
791
+
792
+ let(:genres1) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 3 } ]}
793
+ let(:genres2) { [ { x: 1, y: { z: 1 } }, { x: 2, y: { z: 2 } }, { y: 4 } ]}
794
+ let(:genres3) { [ { x: 1, y: { z: 1 } }, { x: 3, y: { z: 3 } }, { y: 5 } ]}
795
+
796
+ let(:label1) { Label.new(name: "Atlantic") }
797
+ let(:label2) { Label.new(name: "Atlantic") }
798
+ let(:label3) { Label.new(name: "Columbia") }
799
+
800
+ before do
801
+ Band.create!(origin: "tally", name: "Depeche Mode", years: 30, sales: "1E2", label: label1, genres: genres1)
802
+ Band.create!(origin: "tally", name: "New Order", years: 30, sales: "2E3", label: label2, genres: genres2)
803
+ Band.create!(origin: "tally", name: "10,000 Maniacs", years: 30, sales: "1E2", label: label3, genres: genres3)
804
+ Band.create!(origin: "tally2", fanatics: fans1, genres: [1, 2])
805
+ Band.create!(origin: "tally2", fanatics: fans2, genres: [1, 2])
806
+ Band.create!(origin: "tally2", fanatics: fans3, genres: [1, 3])
807
+ end
808
+
809
+ let(:criteria) { Band.where(origin: "tally") }
810
+
811
+ context "when tallying a string" do
812
+ let(:tally) do
813
+ criteria.tally(:name)
814
+ end
815
+
816
+ it "returns the correct hash" do
817
+ expect(tally).to eq("Depeche Mode" => 1, "New Order" => 1, "10,000 Maniacs" => 1)
818
+ end
819
+ end
820
+
821
+ context "using an aliased field" do
822
+ let(:tally) do
823
+ criteria.tally(:years)
824
+ end
825
+
826
+ it "returns the correct hash" do
827
+ expect(tally).to eq(30 => 3)
828
+ end
829
+ end
830
+
831
+ context "when tallying a demongoizable field" do
832
+ let(:tally) do
833
+ criteria.tally(:sales)
834
+ end
835
+
836
+ it "returns the correct hash" do
837
+ expect(tally).to eq(BigDecimal("1E2") => 2, BigDecimal("2E3") => 1)
838
+ end
839
+ end
840
+
841
+ context "when tallying a localized field" do
842
+ before do
843
+ I18n.locale = :en
844
+ d1 = Dictionary.create!(description: 'en1')
845
+ d2 = Dictionary.create!(description: 'en1')
846
+ d3 = Dictionary.create!(description: 'en1')
847
+ d4 = Dictionary.create!(description: 'en2')
848
+ I18n.locale = :de
849
+ d1.description = 'de1'
850
+ d2.description = 'de1'
851
+ d3.description = 'de2'
852
+ d4.description = 'de3'
853
+ d1.save!
854
+ d2.save!
855
+ d3.save!
856
+ d4.save!
857
+ I18n.locale = :en
858
+ end
859
+
860
+ context "when getting the demongoized field" do
861
+ let(:tallied) do
862
+ Dictionary.tally(:description)
863
+ end
864
+
865
+ it "returns the translation for the current locale" do
866
+ expect(tallied).to eq("en1" => 3, "en2" => 1)
867
+ end
868
+ end
869
+
870
+ context "when getting a specific locale" do
871
+ let(:tallied) do
872
+ Dictionary.tally("description.de")
873
+ end
874
+
875
+ it "returns the translation for the the specific locale" do
876
+ expect(tallied).to eq("de1" => 2, "de2" => 1, "de3" => 1)
877
+ end
878
+ end
879
+
880
+ context "when getting the full hash" do
881
+ let(:tallied) do
882
+ Dictionary.tally("description_translations")
883
+ end
884
+
885
+ it "returns the correct hash" do
886
+ expect(tallied).to eq(
887
+ {"de" => "de1", "en" => "en1" } => 2,
888
+ {"de" => "de2", "en" => "en1" } => 1,
889
+ {"de" => "de3", "en" => "en2" } => 1
890
+ )
891
+ end
892
+ end
893
+ end
894
+
895
+ context "when tallying an embedded localized field" do
896
+
897
+ before do
898
+ I18n.locale = :en
899
+ address1a = Address.new(name: "en1")
900
+ address1b = Address.new(name: "en2")
901
+ address2a = Address.new(name: "en1")
902
+ address2b = Address.new(name: "en3")
903
+ I18n.locale = :de
904
+ address1a.name = "de1"
905
+ address1b.name = "de2"
906
+ address2a.name = "de1"
907
+ address2b.name = "de3"
908
+ Person.create!(addresses: [ address1a, address1b ])
909
+ Person.create!(addresses: [ address2a, address2b ])
910
+ I18n.locale = :en
911
+ end
912
+
913
+ context "when getting the demongoized field" do
914
+ let(:tallied) do
915
+ Person.tally("addresses.name")
916
+ end
917
+
918
+ it "returns the translation for the current locale" do
919
+ expect(tallied).to eq(
920
+ [ "en1", "en2" ] => 1,
921
+ [ "en1", "en3" ] => 1,
922
+ )
923
+ end
924
+ end
925
+
926
+ context "when getting a specific locale" do
927
+ let(:tallied) do
928
+ Person.tally("addresses.name.de")
929
+ end
930
+
931
+ it "returns the translation for the the specific locale" do
932
+ expect(tallied).to eq(
933
+ [ "de1", "de2" ] => 1,
934
+ [ "de1", "de3" ] => 1,
935
+ )
936
+ end
937
+ end
938
+
939
+ context "when getting the full hash" do
940
+ let(:tallied) do
941
+ Person.tally("addresses.name_translations")
942
+ end
943
+
944
+ it "returns the correct hash" do
945
+ expect(tallied).to eq(
946
+ [{ "de" => "de1", "en" => "en1" }, { "de" => "de2", "en" => "en2" }] => 1,
947
+ [{ "de" => "de1", "en" => "en1" }, { "de" => "de3", "en" => "en3" }] => 1,
948
+ )
949
+ end
950
+ end
951
+
952
+ end
953
+
954
+ context "when tallying an embedded field" do
955
+ let(:tally) do
956
+ criteria.tally("label.name")
957
+ end
958
+
959
+ it "returns the correct hash" do
960
+ expect(tally).to eq("Atlantic" => 2, "Columbia" => 1)
961
+ end
962
+ end
963
+
964
+ context "when tallying an element in an embeds_many field" do
965
+ let(:criteria) { Band.where(origin: "tally2") }
966
+
967
+ let(:tally) do
968
+ criteria.tally("fanatics.age")
969
+ end
970
+
971
+ it "returns the correct hash" do
972
+ expect(tally).to eq(
973
+ [1, 2] => 2,
974
+ [1, 3] => 1
975
+ )
976
+ end
977
+ end
978
+
979
+ context "when tallying an embeds_many field" do
980
+ let(:criteria) { Band.where(origin: "tally2") }
981
+
982
+ let(:tally) do
983
+ criteria.tally("fanatics")
984
+ end
985
+
986
+ it "returns the correct hash" do
987
+ expect(tally).to eq(
988
+ fans1.map(&:attributes) => 1,
989
+ fans2.map(&:attributes) => 1,
990
+ fans3.map(&:attributes) => 1,
991
+ )
992
+ end
993
+ end
994
+
995
+ context "when tallying a field of type array" do
996
+ let(:criteria) { Band.where(origin: "tally2") }
997
+
998
+ let(:tally) do
999
+ criteria.tally("genres")
1000
+ end
1001
+
1002
+ it "returns the correct hash" do
1003
+ expect(tally).to eq(
1004
+ [1, 2] => 2,
1005
+ [1, 3] => 1
1006
+ )
1007
+ end
1008
+ end
1009
+
1010
+ context "when tallying an element from an array of hashes" do
1011
+ let(:criteria) { Band.where(origin: "tally") }
1012
+
1013
+ let(:tally) do
1014
+ criteria.tally("genres.x")
1015
+ end
1016
+
1017
+ it "returns the correct hash without the nil keys" do
1018
+ expect(tally).to eq(
1019
+ [1, 2] => 2,
1020
+ [1, 3] => 1
1021
+ )
1022
+ end
1023
+ end
1024
+
1025
+ context "when tallying an element from an array of hashes; with duplicate" do
1026
+
1027
+ before do
1028
+ Band.create!(origin: "tally", genres: [ { x: 1 }, {x: 1} ] )
1029
+ end
1030
+
1031
+ let(:criteria) { Band.where(origin: "tally") }
1032
+
1033
+ let(:tally) do
1034
+ criteria.tally("genres.x")
1035
+ end
1036
+
1037
+ it "returns the correct hash without the nil keys" do
1038
+ expect(tally).to eq(
1039
+ [1, 2] => 2,
1040
+ [1, 3] => 1,
1041
+ [1, 1] => 1,
1042
+ )
1043
+ end
1044
+ end
1045
+
1046
+ context "when tallying an aliased field of type array" do
1047
+
1048
+ before do
1049
+ Person.create!(array: [ 1, 2 ])
1050
+ Person.create!(array: [ 1, 3 ])
1051
+ end
1052
+
1053
+ let(:tally) do
1054
+ Person.tally("array")
1055
+ end
1056
+
1057
+ it "returns the correct hash" do
1058
+ expect(tally).to eq(
1059
+ [1, 2] => 1,
1060
+ [1, 3] => 1
1061
+ )
1062
+ end
1063
+ end
1064
+
1065
+ context "when going multiple levels deep in arrays" do
1066
+ let(:criteria) { Band.where(origin: "tally") }
1067
+
1068
+ let(:tally) do
1069
+ criteria.tally("genres.y.z")
1070
+ end
1071
+
1072
+ it "returns the correct hash" do
1073
+ expect(tally).to eq(
1074
+ [1, 2] => 2,
1075
+ [1, 3] => 1
1076
+ )
1077
+ end
1078
+ end
1079
+
1080
+ context "when going multiple levels deep in an array" do
1081
+ let(:criteria) { Band.where(origin: "tally") }
1082
+
1083
+ let(:tally) do
1084
+ criteria.tally("genres.y.z")
1085
+ end
1086
+
1087
+ it "returns the correct hash" do
1088
+ expect(tally).to eq(
1089
+ [1, 2] => 2,
1090
+ [1, 3] => 1
1091
+ )
1092
+ end
1093
+ end
1094
+
1095
+ context "when tallying deeply nested arrays/embedded associations" do
1096
+
1097
+ before do
1098
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
1099
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
1100
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
1101
+ end
1102
+
1103
+ let(:tally) do
1104
+ Person.tally("addresses.code.deepest.array.y.z")
1105
+ end
1106
+
1107
+ it "returns the correct hash" do
1108
+ expect(tally).to eq(
1109
+ [ [ 1, 2 ] ] => 2,
1110
+ [ [ 1, 3 ] ] => 1
1111
+ )
1112
+ end
1113
+ end
1114
+
1115
+ context "when tallying deeply nested arrays/embedded associations" do
1116
+
1117
+ before do
1118
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
1119
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
1120
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))),
1121
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
1122
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))),
1123
+ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
1124
+ end
1125
+
1126
+ let(:tally) do
1127
+ Person.tally("addresses.code.deepest.array.y.z")
1128
+ end
1129
+
1130
+ it "returns the correct hash" do
1131
+ expect(tally).to eq(
1132
+ [ [ 1, 2 ], [ 1, 2 ] ] => 2,
1133
+ [ [ 1, 3 ], [ 1, 3 ] ] => 1
1134
+ )
1135
+ end
1136
+ end
1137
+
1138
+ context "when some keys are missing" do
1139
+ before do
1140
+ 3.times { Band.create!(origin: "tally") }
1141
+ end
1142
+
1143
+ let(:tally) do
1144
+ criteria.tally(:name)
1145
+ end
1146
+
1147
+ it "returns the correct hash" do
1148
+ expect(tally).to eq(
1149
+ "Depeche Mode" => 1,
1150
+ "New Order" => 1,
1151
+ "10,000 Maniacs" => 1,
1152
+ nil => 3
1153
+ )
1154
+ end
1155
+ end
1156
+
1157
+ context "when the first element is an embeds_one" do
1158
+ before do
1159
+ Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ]))
1160
+ Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 2) ]))
1161
+ Person.create!(name: Name.new(translations: [ Translation.new(language: 1), Translation.new(language: 3) ]))
1162
+ end
1163
+
1164
+ let(:tally) do
1165
+ Person.tally("name.translations.language")
1166
+ end
1167
+
1168
+ it "returns the correct hash" do
1169
+ expect(tally).to eq(
1170
+ [1, 2] => 2,
1171
+ [1, 3] => 1
1172
+ )
1173
+ end
1174
+ end
1175
+
1176
+ context "when tallying demongoizable values from typeless fields" do
1177
+
1178
+ let!(:person1) { Person.create!(ssn: /hello/) }
1179
+ let!(:person2) { Person.create!(ssn: BSON::Decimal128.new("1")) }
1180
+ let(:tally) { Person.tally("ssn") }
1181
+
1182
+ context "< BSON 5" do
1183
+ max_bson_version '4.99.99'
1184
+
1185
+ it "stores the correct types in the database" do
1186
+ Person.find(person1.id).attributes["ssn"].should be_a BSON::Regexp::Raw
1187
+ Person.find(person2.id).attributes["ssn"].should be_a BSON::Decimal128
1188
+ end
1189
+
1190
+ it "tallies the correct type" do
1191
+ tally.keys.map(&:class).sort do |a,b|
1192
+ a.to_s <=> b.to_s
1193
+ end.should == [BSON::Decimal128, BSON::Regexp::Raw]
1194
+ end
1195
+ end
1196
+
1197
+ context ">= BSON 5" do
1198
+ min_bson_version "5.0"
1199
+
1200
+ it "stores the correct types in the database" do
1201
+ Person.find(person1.id).ssn.should be_a BSON::Regexp::Raw
1202
+ Person.find(person2.id).ssn.should be_a BigDeimal
1203
+ end
1204
+
1205
+ it "tallies the correct type" do
1206
+ tally.keys.map(&:class).sort do |a,b|
1207
+ a.to_s <=> b.to_s
1208
+ end.should == [BigDecimal, BSON::Regexp::Raw]
1209
+ end
1210
+ end
1211
+ end
1212
+ end
1213
+
800
1214
  describe "#each" do
801
1215
 
802
1216
  before do
@@ -1005,51 +1419,15 @@ describe Mongoid::Contextual::Mongo do
1005
1419
  described_class.new(criteria)
1006
1420
  end
1007
1421
 
1008
- context "when exists? already called" do
1422
+ context "when exists? already called and query cache is enabled" do
1423
+ query_cache_enabled
1009
1424
 
1010
1425
  before do
1011
1426
  context.exists?
1012
1427
  end
1013
1428
 
1014
- it "hits the database again" do
1015
- expect(context).to receive(:view).once.and_call_original
1016
- expect(context).to be_exists
1017
- end
1018
- end
1019
- end
1020
-
1021
- context "when caching is enabled" do
1022
-
1023
- let(:criteria) do
1024
- Band.where(name: "Depeche Mode").cache
1025
- end
1026
-
1027
- let(:context) do
1028
- described_class.new(criteria)
1029
- end
1030
-
1031
- context "when the cache is loaded" do
1032
-
1033
- before do
1034
- context.to_a
1035
- end
1036
-
1037
- it "does not hit the database" do
1038
- expect(context).to receive(:view).never
1039
- expect(context).to be_exists
1040
- end
1041
- end
1042
-
1043
- context "when the cache is not loaded" do
1044
-
1045
- context "when a count has been executed" do
1046
-
1047
- before do
1048
- context.count
1049
- end
1050
-
1051
- it "does not hit the database" do
1052
- expect(context).to receive(:view).never
1429
+ it "does not hit the database again" do
1430
+ expect_no_queries do
1053
1431
  expect(context).to be_exists
1054
1432
  end
1055
1433
  end
@@ -1408,7 +1786,7 @@ describe Mongoid::Contextual::Mongo do
1408
1786
  it "deletes the document from the database" do
1409
1787
  expect {
1410
1788
  depeche.reload
1411
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
1789
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Band with id\(s\)/)
1412
1790
  end
1413
1791
 
1414
1792
  context 'when a collation is specified on the criteria' do
@@ -1433,7 +1811,7 @@ describe Mongoid::Contextual::Mongo do
1433
1811
  it "deletes the document from the database" do
1434
1812
  expect {
1435
1813
  depeche.reload
1436
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
1814
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Band with id\(s\)/)
1437
1815
  end
1438
1816
  end
1439
1817
  end
@@ -1470,6 +1848,10 @@ describe Mongoid::Contextual::Mongo do
1470
1848
  Band.create!(name: "New Order")
1471
1849
  end
1472
1850
 
1851
+ let!(:rolling_stones) do
1852
+ Band.create!(name: "The Rolling Stones")
1853
+ end
1854
+
1473
1855
  context "when the context is not cached" do
1474
1856
 
1475
1857
  let(:criteria) do
@@ -1510,14 +1892,14 @@ describe Mongoid::Contextual::Mongo do
1510
1892
  context "when there is sort on the context" do
1511
1893
 
1512
1894
  it "follows the main sort" do
1513
- expect(context.send(method)).to eq(new_order)
1895
+ expect(context.send(method)).to eq(rolling_stones)
1514
1896
  end
1515
1897
  end
1516
1898
 
1517
1899
  context "when subsequently calling #last" do
1518
1900
 
1519
1901
  it "returns the correct document" do
1520
- expect(context.send(method)).to eq(new_order)
1902
+ expect(context.send(method)).to eq(rolling_stones)
1521
1903
  expect(context.last).to eq(depeche_mode)
1522
1904
  end
1523
1905
  end
@@ -1542,134 +1924,614 @@ describe Mongoid::Contextual::Mongo do
1542
1924
 
1543
1925
  it 'returns the last document, sorted by _id' do
1544
1926
  expect(context.send(method)).to eq(depeche_mode)
1545
- expect(context.last).to eq(new_order)
1927
+ expect(context.last).to eq(rolling_stones)
1546
1928
  end
1547
1929
  end
1930
+ end
1548
1931
 
1549
- context 'with option { sort: :none }' do
1932
+ context 'when the criteria has a sort' do
1550
1933
 
1551
- let(:opts) do
1552
- { id_sort: :none }
1934
+ let(:criteria) do
1935
+ Band.desc(:name)
1936
+ end
1937
+
1938
+ let(:context) do
1939
+ described_class.new(criteria)
1940
+ end
1941
+
1942
+ it 'applies the criteria sort' do
1943
+ expect(context.send(method)).to eq(rolling_stones)
1944
+ end
1945
+
1946
+ context 'when calling #last' do
1947
+
1948
+ it 'applies the criteria sort' do
1949
+ expect(context.send(method)).to eq(rolling_stones)
1950
+ expect(context.last).to eq(depeche_mode)
1553
1951
  end
1952
+ end
1953
+ end
1954
+
1955
+ context "when using .sort" do
1956
+
1957
+ let(:criteria) do
1958
+ Band.all.sort(:name => -1).criteria
1959
+ end
1960
+
1961
+ let(:context) do
1962
+ described_class.new(criteria)
1963
+ end
1964
+
1965
+ context "when there is sort on the context" do
1554
1966
 
1555
- it 'does not apply the sort on _id' do
1556
- expect(context.send(method, opts)).to eq(depeche_mode)
1967
+ it "follows the main sort" do
1968
+ expect(context.send(method)).to eq(rolling_stones)
1557
1969
  end
1970
+ end
1558
1971
 
1559
- context 'when calling #last' do
1972
+ context "when subsequently calling #last" do
1560
1973
 
1561
- it 'does not apply a sort on _id' do
1562
- expect(context.send(method, opts)).to eq(depeche_mode)
1563
- expect(context.last(opts)).to eq(depeche_mode)
1564
- end
1974
+ it "returns the correct document" do
1975
+ expect(context.send(method)).to eq(rolling_stones)
1976
+ expect(context.last).to eq(depeche_mode)
1565
1977
  end
1566
1978
  end
1567
1979
  end
1568
1980
 
1569
- context 'when the criteria has a sort' do
1981
+ context "when the query cache is enabled" do
1982
+ query_cache_enabled
1570
1983
 
1571
1984
  let(:criteria) do
1572
- Band.desc(:name)
1985
+ Band.where(name: "Depeche Mode")
1573
1986
  end
1574
1987
 
1575
1988
  let(:context) do
1576
1989
  described_class.new(criteria)
1577
1990
  end
1578
1991
 
1992
+ context "when first method was called before" do
1579
1993
 
1580
- it 'applies the criteria sort' do
1581
- expect(context.send(method)).to eq(new_order)
1994
+ before do
1995
+ context.first
1996
+ end
1997
+
1998
+ it "returns the first document without touching the database" do
1999
+ expect_no_queries do
2000
+ expect(context.send(method)).to eq(depeche_mode)
2001
+ end
2002
+ end
1582
2003
  end
2004
+ end
1583
2005
 
1584
- context 'when calling #last' do
2006
+ context "when including a limit" do
1585
2007
 
1586
- it 'applies the criteria sort' do
1587
- expect(context.send(method)).to eq(new_order)
1588
- expect(context.last).to eq(depeche_mode)
2008
+ context "when the context is not cached" do
2009
+
2010
+ let(:context) do
2011
+ described_class.new(criteria)
2012
+ end
2013
+
2014
+ context "when the limit is 1" do
2015
+ let(:criteria) do
2016
+ Band.criteria
2017
+ end
2018
+
2019
+ let(:docs) do
2020
+ context.send(method, 1)
2021
+ end
2022
+
2023
+ it "returns an array of documents" do
2024
+ expect(docs).to eq([ depeche_mode ])
2025
+ end
2026
+ end
2027
+
2028
+ context "when the limit is >1" do
2029
+ let(:criteria) do
2030
+ Band.criteria
2031
+ end
2032
+
2033
+ let(:docs) do
2034
+ context.send(method, 2)
2035
+ end
2036
+
2037
+ it "returns the number of documents in order" do
2038
+ expect(docs).to eq([ depeche_mode, new_order ])
2039
+ end
2040
+ end
2041
+
2042
+ context 'when the criteria has a collation' do
2043
+ min_server_version '3.4'
2044
+
2045
+ let(:criteria) do
2046
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
2047
+ end
2048
+
2049
+ it "returns the first matching document" do
2050
+ expect(context.send(method, 1)).to eq([ depeche_mode ])
2051
+ end
1589
2052
  end
1590
2053
  end
1591
2054
 
1592
- context 'with option { sort: :none }' do
2055
+ context "when the query cache is enabled" do
1593
2056
 
1594
- let(:opts) do
1595
- { id_sort: :none }
2057
+ let(:context) do
2058
+ described_class.new(criteria)
1596
2059
  end
1597
2060
 
1598
- it 'applies the criteria sort' do
1599
- expect(context.send(method, opts)).to eq(new_order)
2061
+ context "when calling first beforehand" do
2062
+ query_cache_enabled
2063
+
2064
+ let(:context) do
2065
+ described_class.new(criteria)
2066
+ end
2067
+
2068
+ let(:criteria) do
2069
+ Band.all
2070
+ end
2071
+
2072
+ before do
2073
+ context.first(before_limit)
2074
+ end
2075
+
2076
+ let(:docs) do
2077
+ context.send(method, limit)
2078
+ end
2079
+
2080
+ context "when getting all of the documents before" do
2081
+ let(:before_limit) { 3 }
2082
+
2083
+ context "when getting all of the documents" do
2084
+ let(:limit) { 3 }
2085
+
2086
+ it "returns all documents without touching the database" do
2087
+ expect_no_queries do
2088
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2089
+ end
2090
+ end
2091
+ end
2092
+
2093
+ context "when getting fewer documents" do
2094
+ let(:limit) { 2 }
2095
+
2096
+ it "returns the correct documents without touching the database" do
2097
+ expect_no_queries do
2098
+ expect(docs).to eq([ depeche_mode, new_order ])
2099
+ end
2100
+ end
2101
+ end
2102
+ end
2103
+
2104
+ context "when getting fewer documents before" do
2105
+ let(:before_limit) { 2 }
2106
+
2107
+ context "when getting the same number of documents" do
2108
+ let(:limit) { 2 }
2109
+
2110
+ it "returns the correct documents without touching the database" do
2111
+ expect_no_queries do
2112
+ expect(docs).to eq([ depeche_mode, new_order ])
2113
+ end
2114
+ end
2115
+ end
2116
+
2117
+ context "when getting more documents" do
2118
+ let(:limit) { 3 }
2119
+
2120
+ it "returns the correct documents and touches the database" do
2121
+ expect_query(1) do
2122
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2123
+ end
2124
+ end
2125
+ end
2126
+ end
2127
+
2128
+ context "when getting one document before" do
2129
+ let(:before_limit) { 1 }
2130
+
2131
+ context "when getting one document" do
2132
+ let(:limit) { 1 }
2133
+
2134
+ it "returns the correct documents without touching the database" do
2135
+ expect_no_queries do
2136
+ expect(docs).to eq([ depeche_mode ])
2137
+ end
2138
+ end
2139
+ end
2140
+
2141
+ context "when getting more than one document" do
2142
+ let(:limit) { 3 }
2143
+
2144
+ it "returns the correct documents and touches the database" do
2145
+ expect_query(1) do
2146
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2147
+ end
2148
+ end
2149
+ end
2150
+ end
1600
2151
  end
2152
+ end
2153
+ end
1601
2154
 
1602
- context 'when calling #last' do
2155
+ context "when calling #first then #last and the query cache is enabled" do
2156
+ query_cache_enabled
1603
2157
 
1604
- it 'applies the criteria sort' do
1605
- expect(context.send(method, opts)).to eq(new_order)
1606
- expect(context.last(opts)).to eq(depeche_mode)
2158
+ let(:context) do
2159
+ described_class.new(criteria)
2160
+ end
2161
+
2162
+ let(:criteria) do
2163
+ Band.all
2164
+ end
2165
+
2166
+ before do
2167
+ context.first(before_limit)
2168
+ end
2169
+
2170
+ let(:docs) do
2171
+ context.last(limit)
2172
+ end
2173
+
2174
+ context "when getting one from the beginning and one from the end" do
2175
+ let(:before_limit) { 2 }
2176
+ let(:limit) { 1 }
2177
+
2178
+ it "gets the correct document and hits the database" do
2179
+ expect_query(1) do
2180
+ expect(docs).to eq([rolling_stones])
1607
2181
  end
1608
2182
  end
1609
2183
  end
1610
2184
  end
2185
+ end
2186
+ end
1611
2187
 
1612
- context "when using .sort" do
2188
+ describe "#last" do
2189
+ let!(:depeche_mode) do
2190
+ Band.create!(name: "Depeche Mode")
2191
+ end
2192
+
2193
+ let!(:new_order) do
2194
+ Band.create!(name: "New Order")
2195
+ end
2196
+
2197
+ let!(:rolling_stones) do
2198
+ Band.create!(name: "The Rolling Stones")
2199
+ end
2200
+
2201
+ context "when the context is not cached" do
2202
+
2203
+ let(:criteria) do
2204
+ Band.where(name: "Depeche Mode")
2205
+ end
2206
+
2207
+ let(:context) do
2208
+ described_class.new(criteria)
2209
+ end
2210
+
2211
+ it "returns the last matching document" do
2212
+ expect(context.last).to eq(depeche_mode)
2213
+ end
2214
+
2215
+ context 'when the criteria has a collation' do
2216
+ min_server_version '3.4'
1613
2217
 
1614
2218
  let(:criteria) do
1615
- Band.all.sort(:name => -1).criteria
2219
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
2220
+ end
2221
+
2222
+ it "returns the last matching document" do
2223
+ expect(context.last).to eq(depeche_mode)
2224
+ end
2225
+ end
2226
+ end
2227
+
2228
+ context "when using .desc" do
2229
+
2230
+ let(:criteria) do
2231
+ Band.desc(:name)
2232
+ end
2233
+
2234
+ let(:context) do
2235
+ described_class.new(criteria)
2236
+ end
2237
+
2238
+ context "when there is sort on the context" do
2239
+
2240
+ it "follows the main sort" do
2241
+ expect(context.last).to eq(depeche_mode)
2242
+ end
2243
+ end
2244
+
2245
+ context "when subsequently calling #first" do
2246
+
2247
+ it "returns the correct document" do
2248
+ expect(context.last).to eq(depeche_mode)
2249
+ expect(context.first).to eq(rolling_stones)
2250
+ end
2251
+ end
2252
+ end
2253
+
2254
+ context 'when the criteria has no sort' do
2255
+
2256
+ let(:criteria) do
2257
+ Band.all
2258
+ end
2259
+
2260
+ let(:context) do
2261
+ described_class.new(criteria)
2262
+ end
2263
+
2264
+ it 'applies a sort on _id' do
2265
+ expect(context.last).to eq(rolling_stones)
2266
+ end
2267
+
2268
+ context 'when calling #first' do
2269
+
2270
+ it 'returns the first document, sorted by _id' do
2271
+ expect(context.last).to eq(rolling_stones)
2272
+ expect(context.first).to eq(depeche_mode)
2273
+ end
2274
+ end
2275
+ end
2276
+
2277
+ context 'when the criteria has a sort' do
2278
+
2279
+ let(:criteria) do
2280
+ Band.desc(:name)
2281
+ end
2282
+
2283
+ let(:context) do
2284
+ described_class.new(criteria)
2285
+ end
2286
+
2287
+
2288
+ it 'applies the criteria sort' do
2289
+ expect(context.last).to eq(depeche_mode)
2290
+ end
2291
+
2292
+ context 'when calling #first' do
2293
+
2294
+ it 'applies the criteria sort' do
2295
+ expect(context.last).to eq(depeche_mode)
2296
+ expect(context.first).to eq(rolling_stones)
2297
+ end
2298
+ end
2299
+ end
2300
+
2301
+ context "when using .sort" do
2302
+
2303
+ let(:criteria) do
2304
+ Band.all.sort(:name => -1).criteria
2305
+ end
2306
+
2307
+ let(:context) do
2308
+ described_class.new(criteria)
2309
+ end
2310
+
2311
+ context "when there is sort on the context" do
2312
+
2313
+ it "follows the main sort" do
2314
+ expect(context.last).to eq(depeche_mode)
2315
+ end
2316
+ end
2317
+
2318
+ context "when subsequently calling #first" do
2319
+
2320
+ it "returns the correct document" do
2321
+ expect(context.last).to eq(depeche_mode)
2322
+ expect(context.first).to eq(rolling_stones)
2323
+ end
2324
+ end
2325
+ end
2326
+
2327
+ context "when the query cache is enabled" do
2328
+ query_cache_enabled
2329
+
2330
+ let(:criteria) do
2331
+ Band.where(name: "Depeche Mode")
2332
+ end
2333
+
2334
+ let(:context) do
2335
+ described_class.new(criteria)
2336
+ end
2337
+
2338
+ context "when last method was called before" do
2339
+
2340
+ before do
2341
+ context.last
1616
2342
  end
1617
2343
 
2344
+ it "returns the last document without touching the database" do
2345
+ expect_no_queries do
2346
+ expect(context.last).to eq(depeche_mode)
2347
+ end
2348
+ end
2349
+ end
2350
+ end
2351
+
2352
+ context "when including a limit" do
2353
+
2354
+ context "when the context is not cached" do
2355
+
1618
2356
  let(:context) do
1619
2357
  described_class.new(criteria)
1620
2358
  end
1621
2359
 
1622
- context "when there is sort on the context" do
2360
+ context "when the limit is 1" do
2361
+ let(:criteria) do
2362
+ Band.criteria
2363
+ end
1623
2364
 
1624
- it "follows the main sort" do
1625
- expect(context.send(method)).to eq(new_order)
2365
+ let(:docs) do
2366
+ context.last(1)
2367
+ end
2368
+
2369
+ it "returns an array of documents" do
2370
+ expect(docs).to eq([ rolling_stones ])
1626
2371
  end
1627
2372
  end
1628
2373
 
1629
- context "when subsequently calling #last" do
2374
+ context "when the limit is >1" do
2375
+ let(:criteria) do
2376
+ Band.criteria
2377
+ end
1630
2378
 
1631
- it "returns the correct document" do
1632
- expect(context.send(method)).to eq(new_order)
1633
- expect(context.last).to eq(depeche_mode)
2379
+ let(:docs) do
2380
+ context.last(2)
2381
+ end
2382
+
2383
+ it "returns the number of documents in order" do
2384
+ expect(docs).to eq([ new_order, rolling_stones ])
1634
2385
  end
1635
2386
  end
1636
- end
1637
2387
 
1638
- context "when the context is cached" do
2388
+ context 'when the criteria has a collation' do
2389
+ min_server_version '3.4'
1639
2390
 
1640
- let(:criteria) do
1641
- Band.where(name: "Depeche Mode").cache
2391
+ let(:criteria) do
2392
+ Band.where(name: "DEPECHE MODE").collation(locale: 'en_US', strength: 2)
2393
+ end
2394
+
2395
+ it "returns the first matching document" do
2396
+ expect(context.last(1)).to eq([ depeche_mode ])
2397
+ end
1642
2398
  end
2399
+ end
2400
+
2401
+ context "when the context is cached" do
1643
2402
 
1644
2403
  let(:context) do
1645
2404
  described_class.new(criteria)
1646
2405
  end
1647
2406
 
1648
- context "when the cache is loaded" do
2407
+ context "when query cache is enabled" do
2408
+ query_cache_enabled
2409
+
2410
+ let(:context) do
2411
+ described_class.new(criteria)
2412
+ end
2413
+
2414
+ let(:criteria) do
2415
+ Band.all
2416
+ end
1649
2417
 
1650
2418
  before do
1651
- context.to_a
2419
+ context.last(before_limit)
1652
2420
  end
1653
2421
 
1654
- it "returns the first document without touching the database" do
1655
- expect(context).to receive(:view).never
1656
- expect(context.send(method)).to eq(depeche_mode)
2422
+ let(:docs) do
2423
+ context.last(limit)
1657
2424
  end
1658
- end
1659
2425
 
1660
- context "when first method was called before" do
2426
+ context "when getting all of the documents before" do
2427
+ let(:before_limit) { 3 }
1661
2428
 
1662
- before do
1663
- context.first
2429
+ context "when getting all of the documents" do
2430
+ let(:limit) { 3 }
2431
+
2432
+ it "returns all documents without touching the db" do
2433
+ expect_no_queries do
2434
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2435
+ end
2436
+ end
2437
+ end
2438
+
2439
+ context "when getting fewer documents" do
2440
+ let(:limit) { 2 }
2441
+
2442
+ it "returns the correct documents without touching the db" do
2443
+ expect_no_queries do
2444
+ expect(docs).to eq([ new_order, rolling_stones ])
2445
+ end
2446
+ end
2447
+ end
1664
2448
  end
1665
2449
 
1666
- it "returns the first document without touching the database" do
1667
- expect(context).to receive(:view).never
1668
- expect(context.send(method)).to eq(depeche_mode)
2450
+ context "when getting fewer documents before" do
2451
+ let(:before_limit) { 2 }
2452
+
2453
+ context "when getting the same number of documents" do
2454
+ let(:limit) { 2 }
2455
+
2456
+ it "returns the correct documents without touching the db" do
2457
+ expect_no_queries do
2458
+ expect(docs).to eq([ new_order, rolling_stones ])
2459
+ end
2460
+ end
2461
+ end
2462
+
2463
+ context "when getting more documents" do
2464
+ let(:limit) { 3 }
2465
+
2466
+ it "returns the correct documents and touches the database" do
2467
+ expect_query(1) do
2468
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2469
+ end
2470
+ end
2471
+ end
2472
+ end
2473
+
2474
+ context "when getting one document before" do
2475
+ let(:before_limit) { 1 }
2476
+
2477
+ context "when getting one document" do
2478
+ let(:limit) { 1 }
2479
+
2480
+ it "returns the correct documents without touching the database" do
2481
+ expect_no_queries do
2482
+ expect(docs).to eq([ rolling_stones ])
2483
+ end
2484
+ end
2485
+ end
2486
+
2487
+ context "when getting more than one document" do
2488
+ let(:limit) { 3 }
2489
+
2490
+ it "returns the correct documents and touches the database" do
2491
+ expect_query(1) do
2492
+ expect(docs).to eq([ depeche_mode, new_order, rolling_stones ])
2493
+ end
2494
+ end
2495
+ end
1669
2496
  end
1670
2497
  end
1671
2498
  end
1672
2499
  end
2500
+
2501
+ context "when calling #last then #first and the query cache is enabled" do
2502
+ query_cache_enabled
2503
+
2504
+ let(:context) do
2505
+ described_class.new(criteria)
2506
+ end
2507
+
2508
+ let(:criteria) do
2509
+ Band.all
2510
+ end
2511
+
2512
+ before do
2513
+ context.last(before_limit)
2514
+ end
2515
+
2516
+ let(:docs) do
2517
+ context.first(limit)
2518
+ end
2519
+
2520
+ context "when getting one from the beginning and one from the end" do
2521
+ let(:before_limit) { 2 }
2522
+ let(:limit) { 1 }
2523
+
2524
+ it "hits the database" do
2525
+ expect_query(1) do
2526
+ docs
2527
+ end
2528
+ end
2529
+
2530
+ it "gets the correct document" do
2531
+ expect(docs).to eq([ depeche_mode ])
2532
+ end
2533
+ end
2534
+ end
1673
2535
  end
1674
2536
 
1675
2537
  describe "#initialize" do
@@ -1718,37 +2580,28 @@ describe Mongoid::Contextual::Mongo do
1718
2580
  described_class.new(criteria)
1719
2581
  end
1720
2582
 
1721
- it "returns the number of documents that match" do
1722
- expect(context.send(method)).to eq(2)
1723
- end
2583
+ context "when broken_view_options is false" do
2584
+ driver_config_override :broken_view_options, false
1724
2585
 
1725
- context "when calling more than once" do
1726
- it "returns the cached value for subsequent calls" do
1727
- expect(context.view).to receive(:count_documents).once.and_return(2)
1728
- 2.times { expect(context.send(method)).to eq(2) }
2586
+ it "returns the number of documents that match" do
2587
+ expect(context.send(method)).to eq(1)
1729
2588
  end
1730
2589
  end
1731
2590
 
1732
- context "when the results have been iterated over" do
2591
+ context "when broken_view_options is true" do
2592
+ driver_config_override :broken_view_options, true
1733
2593
 
1734
- before do
1735
- context.entries
1736
- end
1737
-
1738
- it "returns the cached value for all calls" do
1739
- expect(context.view).to receive(:count_documents).once.and_return(2)
2594
+ it "returns the number of documents that match" do
1740
2595
  expect(context.send(method)).to eq(2)
1741
2596
  end
2597
+ end
1742
2598
 
1743
- context "when the results have been iterated over multiple times" do
2599
+ context "when calling more than once with different limits" do
2600
+ driver_config_override :broken_view_options, false
1744
2601
 
1745
- before do
1746
- context.entries
1747
- end
1748
-
1749
- it "resets the length on each full iteration" do
1750
- expect(context.size).to eq(2)
1751
- end
2602
+ it "does not cache the value" do
2603
+ expect(context.limit(1).send(method)).to eq(1)
2604
+ expect(context.limit(2).send(method)).to eq(2)
1752
2605
  end
1753
2606
  end
1754
2607
  end
@@ -1767,10 +2620,12 @@ describe Mongoid::Contextual::Mongo do
1767
2620
  expect(context.send(method)).to eq(1)
1768
2621
  end
1769
2622
 
1770
- context "when calling more than once" do
1771
- it "returns the cached value for subsequent calls" do
1772
- expect(context.view).to receive(:count_documents).once.and_return(1)
1773
- 2.times { expect(context.send(method)).to eq(1) }
2623
+ context "when calling more than once with different skips" do
2624
+ driver_config_override :broken_view_options, false
2625
+
2626
+ it "does not cache the value" do
2627
+ expect(context.skip(0).send(method)).to eq(1)
2628
+ expect(context.skip(1).send(method)).to eq(0)
1774
2629
  end
1775
2630
  end
1776
2631
 
@@ -1823,6 +2678,80 @@ describe Mongoid::Contextual::Mongo do
1823
2678
  end
1824
2679
  end
1825
2680
 
2681
+ describe "#take" do
2682
+
2683
+ let!(:depeche_mode) do
2684
+ Band.create!(name: "Depeche Mode")
2685
+ end
2686
+
2687
+ let!(:new_order) do
2688
+ Band.create!(name: "New Order")
2689
+ end
2690
+
2691
+ let!(:rolling_stones) do
2692
+ Band.create!(name: "The Rolling Stones")
2693
+ end
2694
+
2695
+ let(:criteria) do
2696
+ Band.all
2697
+ end
2698
+
2699
+ let(:context) do
2700
+ described_class.new(criteria)
2701
+ end
2702
+
2703
+ it "takes the correct number results" do
2704
+ expect(context.take(2)).to eq([ depeche_mode, new_order ])
2705
+ end
2706
+
2707
+ it "returns an array when passing 1" do
2708
+ expect(context.take(1)).to eq([ depeche_mode ])
2709
+ end
2710
+
2711
+ it "does not return an array when not passing an argument" do
2712
+ expect(context.take).to eq(depeche_mode)
2713
+ end
2714
+
2715
+ it "returns all the documents taking more than whats in the db" do
2716
+ expect(context.take(5)).to eq([ depeche_mode, new_order, rolling_stones ])
2717
+ end
2718
+ end
2719
+
2720
+ describe "#take!" do
2721
+
2722
+ let!(:depeche_mode) do
2723
+ Band.create!(name: "Depeche Mode")
2724
+ end
2725
+
2726
+ let!(:new_order) do
2727
+ Band.create!(name: "New Order")
2728
+ end
2729
+
2730
+ let!(:rolling_stones) do
2731
+ Band.create!(name: "The Rolling Stones")
2732
+ end
2733
+
2734
+ let(:criteria) do
2735
+ Band.all
2736
+ end
2737
+
2738
+ let(:context) do
2739
+ described_class.new(criteria)
2740
+ end
2741
+
2742
+ it "takes the first document" do
2743
+ expect(context.take!).to eq(depeche_mode)
2744
+ end
2745
+
2746
+ context "when there are no documents" do
2747
+ it "raises an error" do
2748
+ expect do
2749
+ Person.take!
2750
+ end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Person./)
2751
+ end
2752
+ end
2753
+ end
2754
+
1826
2755
  describe "#map" do
1827
2756
 
1828
2757
  before do
@@ -1840,8 +2769,10 @@ describe Mongoid::Contextual::Mongo do
1840
2769
 
1841
2770
  context "when passed the symbol field name" do
1842
2771
 
1843
- it "performs mapping" do
1844
- expect(context.map(:name)).to eq ["Depeche Mode", "New Order"]
2772
+ it "raises an error" do
2773
+ expect do
2774
+ context.map(:name)
2775
+ end.to raise_error(ArgumentError)
1845
2776
  end
1846
2777
  end
1847
2778