mongoid 7.4.0 → 8.0.3

Sign up to get free protection for your applications and to get access to all the features.
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