mongoid 7.0.5 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1107) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +33 -33
  4. data/LICENSE +1 -0
  5. data/README.md +34 -20
  6. data/Rakefile +63 -5
  7. data/lib/config/locales/en.yml +220 -105
  8. data/lib/mongoid/association/accessors.rb +176 -84
  9. data/lib/mongoid/association/bindable.rb +57 -28
  10. data/lib/mongoid/association/builders.rb +9 -15
  11. data/lib/mongoid/association/constrainable.rb +5 -7
  12. data/lib/mongoid/association/depending.rb +9 -18
  13. data/lib/mongoid/association/eager_loadable.rb +31 -10
  14. data/lib/mongoid/association/embedded/batchable.rb +68 -54
  15. data/lib/mongoid/association/embedded/cyclic.rb +10 -17
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +27 -9
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +9 -6
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +16 -25
  19. data/lib/mongoid/association/embedded/embedded_in.rb +9 -28
  20. data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -8
  21. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +10 -6
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +156 -135
  23. data/lib/mongoid/association/embedded/embeds_many.rb +10 -37
  24. data/lib/mongoid/association/embedded/embeds_one/binding.rb +4 -8
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +27 -10
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +64 -30
  27. data/lib/mongoid/association/embedded/embeds_one.rb +11 -34
  28. data/lib/mongoid/association/embedded.rb +2 -0
  29. data/lib/mongoid/association/macros.rb +65 -41
  30. data/lib/mongoid/association/many.rb +25 -35
  31. data/lib/mongoid/association/marshalable.rb +3 -6
  32. data/lib/mongoid/association/nested/many.rb +22 -30
  33. data/lib/mongoid/association/nested/nested_buildable.rb +9 -15
  34. data/lib/mongoid/association/nested/one.rb +57 -30
  35. data/lib/mongoid/association/nested.rb +3 -3
  36. data/lib/mongoid/association/one.rb +5 -12
  37. data/lib/mongoid/association/options.rb +16 -46
  38. data/lib/mongoid/association/proxy.rb +52 -40
  39. data/lib/mongoid/association/referenced/auto_save.rb +9 -14
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +5 -9
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +11 -9
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +40 -3
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +19 -31
  44. data/lib/mongoid/association/referenced/belongs_to.rb +16 -38
  45. data/lib/mongoid/association/referenced/counter_cache.rb +14 -25
  46. data/lib/mongoid/association/referenced/eager.rb +41 -40
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +12 -11
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +5 -5
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +2 -1
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +105 -68
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +29 -46
  52. data/lib/mongoid/association/referenced/has_many/binding.rb +3 -6
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +5 -5
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +2 -1
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +440 -456
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +102 -125
  57. data/lib/mongoid/association/referenced/has_many.rb +21 -45
  58. data/lib/mongoid/association/referenced/has_one/binding.rb +4 -9
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +20 -6
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +2 -1
  61. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +16 -29
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +25 -30
  63. data/lib/mongoid/association/referenced/has_one.rb +16 -36
  64. data/lib/mongoid/association/referenced/syncable.rb +11 -26
  65. data/lib/mongoid/association/referenced.rb +2 -0
  66. data/lib/mongoid/association/reflections.rb +7 -6
  67. data/lib/mongoid/association/relatable.rb +62 -84
  68. data/lib/mongoid/association.rb +13 -27
  69. data/lib/mongoid/atomic/modifiers.rb +29 -53
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +23 -7
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +4 -7
  72. data/lib/mongoid/atomic/paths/embedded.rb +2 -3
  73. data/lib/mongoid/atomic/paths/root.rb +4 -7
  74. data/lib/mongoid/atomic/paths.rb +2 -1
  75. data/lib/mongoid/atomic.rb +42 -47
  76. data/lib/mongoid/attributes/dynamic.rb +22 -36
  77. data/lib/mongoid/attributes/nested.rb +12 -15
  78. data/lib/mongoid/attributes/processing.rb +19 -27
  79. data/lib/mongoid/attributes/projector.rb +119 -0
  80. data/lib/mongoid/attributes/readonly.rb +6 -9
  81. data/lib/mongoid/attributes.rb +103 -100
  82. data/lib/mongoid/cacheable.rb +7 -10
  83. data/lib/mongoid/changeable.rb +151 -70
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +15 -14
  86. data/lib/mongoid/clients/sessions.rb +10 -10
  87. data/lib/mongoid/clients/storage_options.rb +9 -17
  88. data/lib/mongoid/clients/validators/storage.rb +5 -24
  89. data/lib/mongoid/clients/validators.rb +2 -1
  90. data/lib/mongoid/clients.rb +3 -10
  91. data/lib/mongoid/collection_configurable.rb +58 -0
  92. data/lib/mongoid/composable.rb +7 -9
  93. data/lib/mongoid/config/defaults.rb +60 -0
  94. data/lib/mongoid/config/environment.rb +51 -13
  95. data/lib/mongoid/config/options.rb +20 -23
  96. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  97. data/lib/mongoid/config/validators/client.rb +8 -23
  98. data/lib/mongoid/config/validators/option.rb +2 -3
  99. data/lib/mongoid/config/validators.rb +3 -1
  100. data/lib/mongoid/config.rb +235 -48
  101. data/lib/mongoid/contextual/aggregable/memory.rb +40 -27
  102. data/lib/mongoid/contextual/aggregable/mongo.rb +32 -33
  103. data/lib/mongoid/contextual/aggregable/none.rb +65 -0
  104. data/lib/mongoid/contextual/aggregable.rb +17 -0
  105. data/lib/mongoid/contextual/atomic.rb +29 -31
  106. data/lib/mongoid/contextual/command.rb +2 -5
  107. data/lib/mongoid/contextual/geo_near.rb +13 -44
  108. data/lib/mongoid/contextual/map_reduce.rb +7 -35
  109. data/lib/mongoid/contextual/memory.rb +387 -81
  110. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  111. data/lib/mongoid/contextual/mongo.rb +641 -283
  112. data/lib/mongoid/contextual/none.rb +264 -31
  113. data/lib/mongoid/contextual/queryable.rb +3 -4
  114. data/lib/mongoid/contextual.rb +21 -11
  115. data/lib/mongoid/copyable.rb +42 -17
  116. data/lib/mongoid/criteria/findable.rb +20 -20
  117. data/lib/mongoid/criteria/includable.rb +32 -34
  118. data/lib/mongoid/criteria/inspectable.rb +2 -3
  119. data/lib/mongoid/criteria/marshalable.rb +12 -7
  120. data/lib/mongoid/criteria/modifiable.rb +4 -20
  121. data/lib/mongoid/criteria/options.rb +2 -3
  122. data/lib/mongoid/criteria/permission.rb +3 -2
  123. data/lib/mongoid/criteria/queryable/aggregable.rb +4 -15
  124. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  125. data/lib/mongoid/criteria/queryable/extensions/array.rb +7 -41
  126. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +28 -8
  127. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +5 -6
  128. data/lib/mongoid/criteria/queryable/extensions/date.rb +9 -9
  129. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +11 -12
  130. data/lib/mongoid/criteria/queryable/extensions/hash.rb +4 -41
  131. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -14
  132. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -21
  133. data/lib/mongoid/criteria/queryable/extensions/object.rb +6 -30
  134. data/lib/mongoid/criteria/queryable/extensions/range.rb +49 -17
  135. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +12 -19
  136. data/lib/mongoid/criteria/queryable/extensions/set.rb +4 -5
  137. data/lib/mongoid/criteria/queryable/extensions/string.rb +7 -32
  138. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +7 -22
  139. data/lib/mongoid/criteria/queryable/extensions/time.rb +10 -10
  140. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +19 -7
  141. data/lib/mongoid/criteria/queryable/extensions.rb +1 -4
  142. data/lib/mongoid/criteria/queryable/key.rb +40 -25
  143. data/lib/mongoid/criteria/queryable/macroable.rb +3 -4
  144. data/lib/mongoid/criteria/queryable/mergeable.rb +205 -44
  145. data/lib/mongoid/criteria/queryable/optional.rb +16 -65
  146. data/lib/mongoid/criteria/queryable/options.rb +4 -21
  147. data/lib/mongoid/criteria/queryable/pipeline.rb +5 -15
  148. data/lib/mongoid/criteria/queryable/selectable.rb +453 -177
  149. data/lib/mongoid/criteria/queryable/selector.rb +126 -29
  150. data/lib/mongoid/criteria/queryable/smash.rb +42 -18
  151. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  152. data/lib/mongoid/criteria/queryable.rb +18 -15
  153. data/lib/mongoid/criteria/scopable.rb +29 -21
  154. data/lib/mongoid/criteria/translator.rb +45 -0
  155. data/lib/mongoid/criteria.rb +106 -111
  156. data/lib/mongoid/deprecable.rb +36 -0
  157. data/lib/mongoid/deprecation.rb +25 -0
  158. data/lib/mongoid/document.rb +151 -99
  159. data/lib/mongoid/equality.rb +35 -18
  160. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -5
  161. data/lib/mongoid/errors/callback.rb +2 -3
  162. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  163. data/lib/mongoid/errors/criteria_argument_required.rb +18 -0
  164. data/lib/mongoid/errors/delete_restriction.rb +10 -13
  165. data/lib/mongoid/errors/document_not_destroyed.rb +4 -7
  166. data/lib/mongoid/errors/document_not_found.rb +35 -21
  167. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  168. data/lib/mongoid/errors/empty_config_file.rb +25 -0
  169. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  170. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -3
  171. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  172. data/lib/mongoid/errors/invalid_collection.rb +2 -1
  173. data/lib/mongoid/errors/invalid_config_file.rb +25 -0
  174. data/lib/mongoid/errors/invalid_config_option.rb +3 -4
  175. data/lib/mongoid/errors/invalid_dependent_strategy.rb +3 -4
  176. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
  177. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  178. data/lib/mongoid/errors/invalid_elem_match_operator.rb +32 -0
  179. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +25 -0
  180. data/lib/mongoid/errors/invalid_expression_operator.rb +27 -0
  181. data/lib/mongoid/errors/invalid_field.rb +8 -7
  182. data/lib/mongoid/errors/invalid_field_operator.rb +32 -0
  183. data/lib/mongoid/errors/invalid_field_option.rb +2 -3
  184. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  185. data/lib/mongoid/errors/invalid_find.rb +2 -3
  186. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  187. data/lib/mongoid/errors/invalid_includes.rb +2 -3
  188. data/lib/mongoid/errors/invalid_index.rb +2 -3
  189. data/lib/mongoid/errors/invalid_options.rb +4 -5
  190. data/lib/mongoid/errors/invalid_path.rb +2 -3
  191. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -5
  192. data/lib/mongoid/errors/invalid_query.rb +40 -0
  193. data/lib/mongoid/errors/invalid_relation.rb +5 -10
  194. data/lib/mongoid/errors/invalid_relation_option.rb +4 -5
  195. data/lib/mongoid/errors/invalid_scope.rb +2 -3
  196. data/lib/mongoid/errors/invalid_session_use.rb +3 -6
  197. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -5
  198. data/lib/mongoid/errors/invalid_storage_options.rb +3 -4
  199. data/lib/mongoid/errors/invalid_storage_parent.rb +4 -3
  200. data/lib/mongoid/errors/invalid_time.rb +2 -3
  201. data/lib/mongoid/errors/inverse_not_found.rb +3 -4
  202. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -3
  203. data/lib/mongoid/errors/mixed_relations.rb +2 -3
  204. data/lib/mongoid/errors/mongoid_error.rb +6 -13
  205. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -4
  206. data/lib/mongoid/errors/no_client_config.rb +4 -5
  207. data/lib/mongoid/errors/no_client_database.rb +3 -4
  208. data/lib/mongoid/errors/no_client_hosts.rb +3 -4
  209. data/lib/mongoid/errors/no_clients_config.rb +2 -3
  210. data/lib/mongoid/errors/no_default_client.rb +3 -4
  211. data/lib/mongoid/errors/no_environment.rb +2 -3
  212. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -3
  213. data/lib/mongoid/errors/no_metadata.rb +2 -3
  214. data/lib/mongoid/errors/no_parent.rb +2 -3
  215. data/lib/mongoid/errors/readonly_attribute.rb +3 -4
  216. data/lib/mongoid/errors/readonly_document.rb +3 -6
  217. data/lib/mongoid/errors/scope_overwrite.rb +2 -1
  218. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -1
  219. data/lib/mongoid/errors/unknown_attribute.rb +3 -4
  220. data/lib/mongoid/errors/unknown_model.rb +2 -3
  221. data/lib/mongoid/errors/unsaved_document.rb +3 -2
  222. data/lib/mongoid/errors/unsupported_javascript.rb +2 -3
  223. data/lib/mongoid/errors/validations.rb +2 -1
  224. data/lib/mongoid/errors.rb +18 -4
  225. data/lib/mongoid/evolvable.rb +4 -5
  226. data/lib/mongoid/extensions/array.rb +37 -44
  227. data/lib/mongoid/extensions/big_decimal.rb +35 -21
  228. data/lib/mongoid/extensions/binary.rb +42 -0
  229. data/lib/mongoid/extensions/boolean.rb +10 -6
  230. data/lib/mongoid/extensions/date.rb +32 -25
  231. data/lib/mongoid/extensions/date_time.rb +5 -13
  232. data/lib/mongoid/extensions/decimal128.rb +2 -5
  233. data/lib/mongoid/extensions/false_class.rb +5 -8
  234. data/lib/mongoid/extensions/float.rb +12 -14
  235. data/lib/mongoid/extensions/hash.rb +64 -42
  236. data/lib/mongoid/extensions/integer.rb +12 -16
  237. data/lib/mongoid/extensions/module.rb +3 -4
  238. data/lib/mongoid/extensions/nil_class.rb +2 -5
  239. data/lib/mongoid/extensions/object.rb +27 -52
  240. data/lib/mongoid/extensions/object_id.rb +2 -7
  241. data/lib/mongoid/extensions/range.rb +42 -20
  242. data/lib/mongoid/extensions/regexp.rb +14 -8
  243. data/lib/mongoid/extensions/set.rb +13 -11
  244. data/lib/mongoid/extensions/string.rb +30 -61
  245. data/lib/mongoid/extensions/symbol.rb +6 -22
  246. data/lib/mongoid/extensions/time.rb +38 -22
  247. data/lib/mongoid/extensions/time_with_zone.rb +26 -9
  248. data/lib/mongoid/extensions/true_class.rb +5 -8
  249. data/lib/mongoid/extensions.rb +19 -3
  250. data/lib/mongoid/factory.rb +104 -17
  251. data/lib/mongoid/fields/foreign_key.rb +14 -26
  252. data/lib/mongoid/fields/localized.rb +21 -15
  253. data/lib/mongoid/fields/standard.rb +23 -43
  254. data/lib/mongoid/fields/validators/macro.rb +32 -20
  255. data/lib/mongoid/fields/validators.rb +2 -1
  256. data/lib/mongoid/fields.rb +349 -76
  257. data/lib/mongoid/findable.rb +115 -34
  258. data/lib/mongoid/indexable/specification.rb +5 -18
  259. data/lib/mongoid/indexable/validators/options.rb +8 -9
  260. data/lib/mongoid/indexable.rb +6 -21
  261. data/lib/mongoid/inspectable.rb +4 -11
  262. data/lib/mongoid/interceptable.rb +85 -41
  263. data/lib/mongoid/loggable.rb +13 -16
  264. data/lib/mongoid/matchable.rb +4 -156
  265. data/lib/mongoid/matcher/all.rb +22 -0
  266. data/lib/mongoid/matcher/and.rb +21 -0
  267. data/lib/mongoid/matcher/bits.rb +41 -0
  268. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  269. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  270. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  271. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  272. data/lib/mongoid/matcher/elem_match.rb +36 -0
  273. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  274. data/lib/mongoid/matcher/eq.rb +11 -0
  275. data/lib/mongoid/matcher/eq_impl.rb +67 -0
  276. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +26 -0
  277. data/lib/mongoid/matcher/exists.rb +15 -0
  278. data/lib/mongoid/matcher/expression.rb +35 -0
  279. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  280. data/lib/mongoid/matcher/field_expression.rb +62 -0
  281. data/lib/mongoid/matcher/field_operator.rb +54 -0
  282. data/lib/mongoid/matcher/gt.rb +17 -0
  283. data/lib/mongoid/matcher/gte.rb +17 -0
  284. data/lib/mongoid/matcher/in.rb +25 -0
  285. data/lib/mongoid/matcher/lt.rb +17 -0
  286. data/lib/mongoid/matcher/lte.rb +17 -0
  287. data/lib/mongoid/matcher/mod.rb +17 -0
  288. data/lib/mongoid/matcher/ne.rb +16 -0
  289. data/lib/mongoid/matcher/nin.rb +11 -0
  290. data/lib/mongoid/matcher/nor.rb +25 -0
  291. data/lib/mongoid/matcher/not.rb +29 -0
  292. data/lib/mongoid/matcher/or.rb +21 -0
  293. data/lib/mongoid/matcher/regex.rb +41 -0
  294. data/lib/mongoid/matcher/size.rb +26 -0
  295. data/lib/mongoid/matcher/type.rb +99 -0
  296. data/lib/mongoid/matcher.rb +130 -0
  297. data/lib/mongoid/persistable/creatable.rb +23 -30
  298. data/lib/mongoid/persistable/deletable.rb +7 -23
  299. data/lib/mongoid/persistable/destroyable.rb +12 -11
  300. data/lib/mongoid/persistable/incrementable.rb +6 -7
  301. data/lib/mongoid/persistable/logical.rb +4 -6
  302. data/lib/mongoid/persistable/poppable.rb +3 -6
  303. data/lib/mongoid/persistable/pullable.rb +3 -8
  304. data/lib/mongoid/persistable/pushable.rb +14 -10
  305. data/lib/mongoid/persistable/renamable.rb +10 -8
  306. data/lib/mongoid/persistable/savable.rb +16 -9
  307. data/lib/mongoid/persistable/settable.rb +3 -6
  308. data/lib/mongoid/persistable/unsettable.rb +10 -10
  309. data/lib/mongoid/persistable/updatable.rb +99 -30
  310. data/lib/mongoid/persistable/upsertable.rb +23 -9
  311. data/lib/mongoid/persistable.rb +138 -40
  312. data/lib/mongoid/persistence_context.rb +91 -51
  313. data/lib/mongoid/positional.rb +2 -5
  314. data/lib/mongoid/query_cache.rb +18 -238
  315. data/lib/mongoid/railtie.rb +3 -16
  316. data/lib/mongoid/railties/controller_runtime.rb +4 -2
  317. data/lib/mongoid/railties/database.rake +16 -2
  318. data/lib/mongoid/reloadable.rb +21 -22
  319. data/lib/mongoid/scopable.rb +34 -57
  320. data/lib/mongoid/selectable.rb +8 -18
  321. data/lib/mongoid/serializable.rb +33 -34
  322. data/lib/mongoid/shardable.rb +108 -21
  323. data/lib/mongoid/stateful.rb +60 -20
  324. data/lib/mongoid/stringified_symbol.rb +52 -0
  325. data/lib/mongoid/tasks/database.rake +24 -5
  326. data/lib/mongoid/tasks/database.rb +105 -7
  327. data/lib/mongoid/threaded/lifecycle.rb +7 -26
  328. data/lib/mongoid/threaded.rb +44 -67
  329. data/lib/mongoid/timestamps/created/short.rb +2 -1
  330. data/lib/mongoid/timestamps/created.rb +4 -3
  331. data/lib/mongoid/timestamps/short.rb +2 -1
  332. data/lib/mongoid/timestamps/timeless.rb +6 -9
  333. data/lib/mongoid/timestamps/updated/short.rb +2 -1
  334. data/lib/mongoid/timestamps/updated.rb +5 -6
  335. data/lib/mongoid/timestamps.rb +3 -2
  336. data/lib/mongoid/touchable.rb +54 -25
  337. data/lib/mongoid/traversable.rb +185 -61
  338. data/lib/mongoid/utils.rb +22 -0
  339. data/lib/mongoid/validatable/associated.rb +5 -6
  340. data/lib/mongoid/validatable/format.rb +2 -1
  341. data/lib/mongoid/validatable/length.rb +2 -1
  342. data/lib/mongoid/validatable/localizable.rb +3 -4
  343. data/lib/mongoid/validatable/macros.rb +7 -14
  344. data/lib/mongoid/validatable/presence.rb +10 -15
  345. data/lib/mongoid/validatable/queryable.rb +2 -3
  346. data/lib/mongoid/validatable/uniqueness.rb +30 -42
  347. data/lib/mongoid/validatable.rb +16 -32
  348. data/lib/mongoid/version.rb +3 -2
  349. data/lib/mongoid/warnings.rb +44 -0
  350. data/lib/mongoid.rb +50 -17
  351. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  352. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +53 -32
  353. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  354. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  355. data/lib/rails/generators/mongoid_generator.rb +2 -1
  356. data/lib/rails/mongoid.rb +4 -5
  357. data/spec/README.md +19 -4
  358. data/spec/config/mongoid.yml +17 -0
  359. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  360. data/spec/integration/app_spec.rb +345 -0
  361. data/spec/integration/associations/belongs_to_spec.rb +20 -0
  362. data/spec/integration/associations/embedded_dirty_spec.rb +57 -0
  363. data/spec/integration/associations/embedded_spec.rb +283 -0
  364. data/spec/integration/associations/embeds_many_spec.rb +219 -0
  365. data/spec/integration/associations/embeds_one_spec.rb +41 -0
  366. data/spec/integration/associations/foreign_key_spec.rb +107 -0
  367. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  368. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  369. data/spec/integration/associations/has_many_spec.rb +128 -0
  370. data/spec/integration/associations/has_one_spec.rb +272 -0
  371. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  372. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  373. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  374. data/spec/integration/associations/scope_option_spec.rb +101 -0
  375. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  376. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  377. data/spec/integration/callbacks_models.rb +192 -0
  378. data/spec/integration/callbacks_spec.rb +584 -0
  379. data/spec/integration/contextual/empty_spec.rb +141 -0
  380. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  381. data/spec/integration/criteria/date_field_spec.rb +40 -0
  382. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  383. data/spec/integration/criteria/logical_spec.rb +124 -0
  384. data/spec/integration/criteria/range_spec.rb +359 -0
  385. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  386. data/spec/integration/discriminator_key_spec.rb +391 -0
  387. data/spec/integration/discriminator_value_spec.rb +206 -0
  388. data/spec/integration/document_spec.rb +51 -0
  389. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  390. data/spec/integration/i18n_fallbacks_spec.rb +74 -0
  391. data/spec/integration/matcher_examples_spec.rb +765 -0
  392. data/spec/integration/matcher_operator_data/all.yml +140 -0
  393. data/spec/integration/matcher_operator_data/and.yml +93 -0
  394. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  395. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  396. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  397. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  398. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  399. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  400. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  401. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  402. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  403. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  404. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  405. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  406. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  407. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  408. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  409. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  410. data/spec/integration/matcher_operator_data/in.yml +210 -0
  411. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  412. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  413. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  414. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  415. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  416. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  417. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  418. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  419. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  420. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  421. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  422. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  423. data/spec/integration/matcher_operator_data/not.yml +196 -0
  424. data/spec/integration/matcher_operator_data/or.yml +137 -0
  425. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  426. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  427. data/spec/integration/matcher_operator_data/size.yml +174 -0
  428. data/spec/integration/matcher_operator_data/type.yml +70 -0
  429. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  430. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  431. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  432. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  433. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  434. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  435. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  436. data/spec/integration/matcher_operator_data/type_decimal.yml +41 -0
  437. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  438. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  439. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  440. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  441. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  442. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  443. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  444. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  445. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  446. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  447. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  448. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  449. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  450. data/spec/integration/matcher_operator_spec.rb +122 -0
  451. data/spec/integration/matcher_spec.rb +283 -0
  452. data/spec/integration/persistence/range_field_spec.rb +350 -0
  453. data/spec/integration/server_query_spec.rb +141 -0
  454. data/spec/integration/shardable_spec.rb +148 -0
  455. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  456. data/spec/lite_spec_helper.rb +35 -8
  457. data/spec/mongoid/association/accessors_spec.rb +284 -77
  458. data/spec/mongoid/association/auto_save_spec.rb +74 -33
  459. data/spec/mongoid/association/builders_spec.rb +3 -1
  460. data/spec/mongoid/association/constrainable_spec.rb +2 -0
  461. data/spec/mongoid/association/counter_cache_spec.rb +35 -33
  462. data/spec/mongoid/association/depending_spec.rb +431 -338
  463. data/spec/mongoid/association/eager_spec.rb +8 -5
  464. data/spec/mongoid/association/embedded/cyclic_spec.rb +4 -2
  465. data/spec/mongoid/association/embedded/dirty_spec.rb +4 -2
  466. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +4 -1
  467. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +56 -0
  468. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +152 -13
  469. data/spec/mongoid/association/embedded/embedded_in_spec.rb +3 -1
  470. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +2 -0
  471. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +114 -0
  472. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +706 -197
  473. data/spec/mongoid/association/embedded/embeds_many_models.rb +227 -0
  474. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +63 -0
  475. data/spec/mongoid/association/embedded/embeds_many_spec.rb +81 -1
  476. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +2 -0
  477. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +27 -0
  478. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +38 -23
  479. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +2 -0
  480. data/spec/mongoid/association/embedded/embeds_one_models.rb +22 -0
  481. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  482. data/spec/mongoid/association/embedded/embeds_one_spec.rb +31 -3
  483. data/spec/mongoid/association/macros_spec.rb +11 -9
  484. data/spec/mongoid/association/nested/many_spec.rb +2 -0
  485. data/spec/mongoid/association/nested/one_spec.rb +18 -12
  486. data/spec/mongoid/association/options_spec.rb +2 -0
  487. data/spec/mongoid/association/polymorphic_spec.rb +2 -0
  488. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +4 -1
  489. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +111 -16
  490. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +242 -12
  491. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +114 -58
  492. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  493. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  494. data/spec/mongoid/association/referenced/belongs_to_spec.rb +28 -21
  495. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +3 -1
  496. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +28 -1
  497. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +46 -2
  498. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +25 -5
  499. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +559 -385
  500. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +68 -2
  501. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  502. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +81 -4
  503. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +3 -1
  504. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +132 -0
  505. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +40 -9
  506. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +415 -129
  507. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +859 -502
  508. data/spec/mongoid/association/referenced/has_many_models.rb +61 -1
  509. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  510. data/spec/mongoid/association/referenced/has_many_spec.rb +48 -0
  511. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +2 -0
  512. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +55 -9
  513. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +34 -4
  514. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +135 -27
  515. data/spec/mongoid/association/referenced/has_one_models.rb +65 -0
  516. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  517. data/spec/mongoid/association/referenced/has_one_spec.rb +24 -1
  518. data/spec/mongoid/association/reflections_spec.rb +2 -0
  519. data/spec/mongoid/association/syncable_spec.rb +48 -32
  520. data/spec/mongoid/association_spec.rb +2 -0
  521. data/spec/mongoid/atomic/modifiers_spec.rb +49 -0
  522. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  523. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  524. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  525. data/spec/mongoid/atomic/paths_spec.rb +93 -12
  526. data/spec/mongoid/atomic_spec.rb +53 -6
  527. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  528. data/spec/mongoid/attributes/nested_spec.rb +149 -78
  529. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  530. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  531. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  532. data/spec/mongoid/attributes/projector_spec.rb +40 -0
  533. data/spec/mongoid/attributes/readonly_spec.rb +24 -22
  534. data/spec/mongoid/attributes_spec.rb +895 -54
  535. data/spec/mongoid/cacheable_spec.rb +6 -4
  536. data/spec/mongoid/changeable_spec.rb +484 -67
  537. data/spec/mongoid/clients/factory_spec.rb +128 -28
  538. data/spec/mongoid/clients/options_spec.rb +49 -30
  539. data/spec/mongoid/clients/sessions_spec.rb +29 -66
  540. data/spec/mongoid/clients/transactions_spec.rb +74 -37
  541. data/spec/mongoid/clients_spec.rb +189 -23
  542. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  543. data/spec/mongoid/composable_spec.rb +2 -0
  544. data/spec/mongoid/config/defaults_spec.rb +160 -0
  545. data/spec/mongoid/config/environment_spec.rb +126 -8
  546. data/spec/mongoid/config/options_spec.rb +22 -3
  547. data/spec/mongoid/config_spec.rb +504 -1
  548. data/spec/mongoid/contextual/aggregable/memory_spec.rb +433 -153
  549. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  550. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  551. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  552. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  553. data/spec/mongoid/contextual/atomic_spec.rb +242 -81
  554. data/spec/mongoid/contextual/geo_near_spec.rb +30 -19
  555. data/spec/mongoid/contextual/map_reduce_spec.rb +22 -19
  556. data/spec/mongoid/contextual/memory_spec.rb +1828 -303
  557. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  558. data/spec/mongoid/contextual/mongo_spec.rb +3504 -1270
  559. data/spec/mongoid/contextual/none_spec.rb +80 -67
  560. data/spec/mongoid/copyable_spec.rb +659 -36
  561. data/spec/mongoid/copyable_spec_models.rb +30 -0
  562. data/spec/mongoid/criteria/findable_spec.rb +161 -228
  563. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  564. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  565. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  566. data/spec/mongoid/criteria/marshalable_spec.rb +20 -1
  567. data/spec/mongoid/criteria/modifiable_spec.rb +43 -40
  568. data/spec/mongoid/criteria/options_spec.rb +2 -0
  569. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -1
  570. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  571. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +9 -19
  572. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +136 -26
  573. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -1
  574. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +13 -0
  575. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +46 -17
  576. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +2 -0
  577. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +2 -15
  578. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +2 -0
  579. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +2 -0
  580. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -8
  581. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +2 -0
  582. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +239 -178
  583. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -1
  584. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +9 -7
  585. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +2 -0
  586. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +7 -70
  587. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -59
  588. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +53 -23
  589. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +41 -1
  590. data/spec/mongoid/criteria/queryable/key_spec.rb +2 -0
  591. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +145 -12
  592. data/spec/mongoid/criteria/queryable/optional_spec.rb +18 -485
  593. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -1
  594. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +2 -0
  595. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -1
  596. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2538 -0
  597. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  598. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1100 -2880
  599. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  600. data/spec/mongoid/criteria/queryable/selector_spec.rb +17 -3
  601. data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
  602. data/spec/mongoid/criteria/queryable/storable_spec.rb +226 -0
  603. data/spec/mongoid/criteria/scopable_spec.rb +129 -0
  604. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  605. data/spec/mongoid/criteria_projection_spec.rb +406 -0
  606. data/spec/mongoid/criteria_spec.rb +1320 -1723
  607. data/spec/mongoid/document_fields_spec.rb +262 -0
  608. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  609. data/spec/mongoid/document_query_spec.rb +89 -0
  610. data/spec/mongoid/document_spec.rb +153 -87
  611. data/spec/mongoid/equality_spec.rb +144 -41
  612. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  613. data/spec/mongoid/errors/callback_spec.rb +2 -0
  614. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  615. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  616. data/spec/mongoid/errors/document_not_found_spec.rb +78 -0
  617. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  618. data/spec/mongoid/errors/{eager_load_spec.rb → invalid_config_file_spec.rb} +7 -5
  619. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  620. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  621. data/spec/mongoid/errors/invalid_field_spec.rb +3 -1
  622. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  623. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  624. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  625. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  626. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  627. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  628. data/spec/mongoid/errors/invalid_relation_spec.rb +4 -2
  629. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  630. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  631. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  632. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  633. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  634. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  635. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  636. data/spec/mongoid/errors/mongoid_error_spec.rb +24 -8
  637. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  638. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  639. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  640. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  641. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  642. data/spec/mongoid/errors/no_environment_spec.rb +5 -3
  643. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  644. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  645. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  646. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  647. data/spec/mongoid/errors/readonly_document_spec.rb +4 -2
  648. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  649. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -1
  650. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  651. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  652. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  653. data/spec/mongoid/errors/validations_spec.rb +2 -0
  654. data/spec/mongoid/extensions/array_spec.rb +41 -45
  655. data/spec/mongoid/extensions/big_decimal_spec.rb +714 -212
  656. data/spec/mongoid/extensions/binary_spec.rb +46 -9
  657. data/spec/mongoid/extensions/boolean_spec.rb +70 -82
  658. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +339 -0
  659. data/spec/mongoid/extensions/date_spec.rb +58 -140
  660. data/spec/mongoid/extensions/date_time_spec.rb +32 -69
  661. data/spec/mongoid/extensions/decimal128_spec.rb +2 -0
  662. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  663. data/spec/mongoid/extensions/float_spec.rb +66 -73
  664. data/spec/mongoid/extensions/hash_spec.rb +135 -0
  665. data/spec/mongoid/extensions/integer_spec.rb +61 -63
  666. data/spec/mongoid/extensions/module_spec.rb +2 -0
  667. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  668. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  669. data/spec/mongoid/extensions/object_spec.rb +13 -24
  670. data/spec/mongoid/extensions/range_spec.rb +257 -54
  671. data/spec/mongoid/extensions/regexp_spec.rb +60 -33
  672. data/spec/mongoid/extensions/set_spec.rb +108 -0
  673. data/spec/mongoid/extensions/string_spec.rb +111 -50
  674. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  675. data/spec/mongoid/extensions/symbol_spec.rb +20 -25
  676. data/spec/mongoid/extensions/time_spec.rb +668 -106
  677. data/spec/mongoid/extensions/time_with_zone_spec.rb +57 -83
  678. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  679. data/spec/mongoid/extensions_spec.rb +16 -2
  680. data/spec/mongoid/factory_spec.rb +347 -27
  681. data/spec/mongoid/fields/foreign_key_spec.rb +2 -0
  682. data/spec/mongoid/fields/localized_spec.rb +86 -41
  683. data/spec/mongoid/fields/standard_spec.rb +2 -0
  684. data/spec/mongoid/fields_spec.rb +869 -114
  685. data/spec/mongoid/findable_spec.rb +520 -64
  686. data/spec/mongoid/indexable/specification_spec.rb +4 -2
  687. data/spec/mongoid/indexable_spec.rb +87 -32
  688. data/spec/mongoid/inspectable_spec.rb +39 -2
  689. data/spec/mongoid/interceptable_spec.rb +761 -98
  690. data/spec/mongoid/interceptable_spec_models.rb +307 -0
  691. data/spec/mongoid/loggable_spec.rb +2 -0
  692. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  693. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  694. data/spec/mongoid/matcher/extract_attribute_spec.rb +36 -0
  695. data/spec/mongoid/mongoizable_spec.rb +285 -0
  696. data/spec/mongoid/persistable/creatable_spec.rb +114 -29
  697. data/spec/mongoid/persistable/deletable_spec.rb +300 -18
  698. data/spec/mongoid/persistable/destroyable_spec.rb +228 -18
  699. data/spec/mongoid/persistable/incrementable_spec.rb +60 -7
  700. data/spec/mongoid/persistable/logical_spec.rb +56 -3
  701. data/spec/mongoid/persistable/poppable_spec.rb +55 -3
  702. data/spec/mongoid/persistable/pullable_spec.rb +108 -6
  703. data/spec/mongoid/persistable/pushable_spec.rb +163 -7
  704. data/spec/mongoid/persistable/renamable_spec.rb +54 -2
  705. data/spec/mongoid/persistable/savable_spec.rb +284 -25
  706. data/spec/mongoid/persistable/settable_spec.rb +91 -8
  707. data/spec/mongoid/persistable/unsettable_spec.rb +55 -3
  708. data/spec/mongoid/persistable/updatable_spec.rb +63 -49
  709. data/spec/mongoid/persistable/upsertable_spec.rb +93 -3
  710. data/spec/mongoid/persistable_spec.rb +85 -9
  711. data/spec/mongoid/persistence_context_spec.rb +59 -58
  712. data/spec/mongoid/positional_spec.rb +2 -0
  713. data/spec/mongoid/query_cache_middleware_spec.rb +50 -0
  714. data/spec/mongoid/query_cache_spec.rb +410 -95
  715. data/spec/mongoid/relations/proxy_spec.rb +9 -7
  716. data/spec/mongoid/reloadable_spec.rb +357 -26
  717. data/spec/mongoid/scopable_spec.rb +193 -38
  718. data/spec/mongoid/selectable_spec.rb +8 -6
  719. data/spec/mongoid/serializable_spec.rb +148 -38
  720. data/spec/mongoid/shardable_models.rb +75 -0
  721. data/spec/mongoid/shardable_spec.rb +239 -34
  722. data/spec/mongoid/stateful_spec.rb +153 -9
  723. data/spec/mongoid/tasks/database_rake_spec.rb +89 -13
  724. data/spec/mongoid/tasks/database_spec.rb +130 -1
  725. data/spec/mongoid/threaded_spec.rb +4 -2
  726. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  727. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  728. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  729. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  730. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  731. data/spec/mongoid/timestamps_spec.rb +400 -10
  732. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  733. data/spec/mongoid/touchable_spec.rb +568 -33
  734. data/spec/mongoid/touchable_spec_models.rb +59 -0
  735. data/spec/mongoid/traversable_spec.rb +1145 -1
  736. data/spec/mongoid/validatable/associated_spec.rb +2 -0
  737. data/spec/mongoid/validatable/format_spec.rb +2 -0
  738. data/spec/mongoid/validatable/length_spec.rb +2 -0
  739. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  740. data/spec/mongoid/validatable/presence_spec.rb +28 -22
  741. data/spec/mongoid/validatable/uniqueness_spec.rb +159 -103
  742. data/spec/mongoid/validatable_spec.rb +5 -3
  743. data/spec/mongoid/warnings_spec.rb +35 -0
  744. data/spec/mongoid_spec.rb +37 -9
  745. data/spec/rails/controller_extension/controller_runtime_spec.rb +5 -3
  746. data/spec/rails/mongoid_spec.rb +8 -18
  747. data/spec/shared/LICENSE +20 -0
  748. data/spec/shared/bin/get-mongodb-download-url +17 -0
  749. data/spec/shared/bin/s3-copy +45 -0
  750. data/spec/shared/bin/s3-upload +69 -0
  751. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  752. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  753. data/spec/shared/lib/mrss/constraints.rb +378 -0
  754. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  755. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  756. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  757. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  758. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  759. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  760. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  761. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  762. data/spec/shared/lib/mrss/utils.rb +37 -0
  763. data/spec/shared/share/Dockerfile.erb +321 -0
  764. data/spec/shared/share/haproxy-1.conf +16 -0
  765. data/spec/shared/share/haproxy-2.conf +17 -0
  766. data/spec/shared/shlib/config.sh +27 -0
  767. data/spec/shared/shlib/distro.sh +74 -0
  768. data/spec/shared/shlib/server.sh +416 -0
  769. data/spec/shared/shlib/set_env.sh +169 -0
  770. data/spec/spec_helper.rb +44 -66
  771. data/spec/support/authorization.rb +2 -0
  772. data/spec/support/client_registry.rb +9 -0
  773. data/spec/support/constraints.rb +45 -69
  774. data/spec/support/expectations.rb +21 -3
  775. data/spec/support/helpers.rb +11 -0
  776. data/spec/support/immutable_ids.rb +118 -0
  777. data/spec/support/macros.rb +109 -0
  778. data/spec/{app → support}/models/account.rb +3 -1
  779. data/spec/{app → support}/models/acolyte.rb +2 -0
  780. data/spec/{app → support}/models/actor.rb +3 -1
  781. data/spec/support/models/actress.rb +4 -0
  782. data/spec/{app → support}/models/address.rb +6 -0
  783. data/spec/{app → support}/models/address_component.rb +2 -0
  784. data/spec/{app → support}/models/address_number.rb +2 -0
  785. data/spec/{app → support}/models/agency.rb +2 -0
  786. data/spec/{app → support}/models/agent.rb +2 -0
  787. data/spec/{app → support}/models/album.rb +2 -0
  788. data/spec/{app → support}/models/alert.rb +2 -0
  789. data/spec/{app → support}/models/animal.rb +2 -0
  790. data/spec/{app → support}/models/answer.rb +2 -0
  791. data/spec/{app → support}/models/appointment.rb +2 -0
  792. data/spec/support/models/armrest.rb +9 -0
  793. data/spec/{app → support}/models/article.rb +2 -0
  794. data/spec/{app → support}/models/artist.rb +4 -1
  795. data/spec/{app → support}/models/artwork.rb +2 -0
  796. data/spec/support/models/audible_sound.rb +3 -0
  797. data/spec/{app → support}/models/audio.rb +2 -0
  798. data/spec/support/models/augmentation.rb +25 -0
  799. data/spec/{app → support}/models/author.rb +2 -0
  800. data/spec/{app → support}/models/baby.rb +2 -0
  801. data/spec/{app → support}/models/band.rb +10 -0
  802. data/spec/{app → support}/models/bar.rb +2 -0
  803. data/spec/{app → support}/models/basic.rb +2 -0
  804. data/spec/support/models/bed.rb +3 -0
  805. data/spec/{app → support}/models/big_palette.rb +2 -0
  806. data/spec/{app → support}/models/birthday.rb +2 -0
  807. data/spec/support/models/bolt.rb +7 -0
  808. data/spec/{app → support}/models/bomb.rb +2 -0
  809. data/spec/{app → support}/models/book.rb +3 -0
  810. data/spec/{app → support}/models/breed.rb +2 -0
  811. data/spec/{app → support}/models/browser.rb +3 -1
  812. data/spec/{app → support}/models/building.rb +4 -0
  813. data/spec/{app → support}/models/building_address.rb +2 -0
  814. data/spec/{app → support}/models/bus.rb +2 -0
  815. data/spec/{app → support}/models/business.rb +2 -0
  816. data/spec/{app → support}/models/callback_test.rb +2 -0
  817. data/spec/{app → support}/models/canvas.rb +3 -1
  818. data/spec/support/models/car.rb +3 -0
  819. data/spec/{app → support}/models/cat.rb +2 -0
  820. data/spec/support/models/catalog.rb +24 -0
  821. data/spec/{app → support}/models/category.rb +2 -0
  822. data/spec/{app → support}/models/child.rb +2 -0
  823. data/spec/{app → support}/models/child_doc.rb +5 -3
  824. data/spec/{app → support}/models/church.rb +2 -0
  825. data/spec/{app → support}/models/circle.rb +2 -0
  826. data/spec/{app → support}/models/circuit.rb +2 -0
  827. data/spec/support/models/circus.rb +12 -0
  828. data/spec/{app → support}/models/code.rb +4 -0
  829. data/spec/support/models/coding/pull_request.rb +11 -0
  830. data/spec/support/models/coding.rb +3 -0
  831. data/spec/{app → support}/models/comment.rb +2 -0
  832. data/spec/{app → support}/models/company.rb +2 -0
  833. data/spec/{app → support}/models/consumption_period.rb +2 -0
  834. data/spec/{app → support}/models/contextable_item.rb +2 -0
  835. data/spec/{app → support}/models/contractor.rb +2 -0
  836. data/spec/{app → support}/models/cookie.rb +2 -0
  837. data/spec/{app → support}/models/country_code.rb +4 -0
  838. data/spec/{app → support}/models/courier_job.rb +2 -0
  839. data/spec/support/models/cover.rb +10 -0
  840. data/spec/support/models/crate.rb +12 -0
  841. data/spec/support/models/customer.rb +10 -0
  842. data/spec/support/models/customer_address.rb +11 -0
  843. data/spec/support/models/deed.rb +7 -0
  844. data/spec/{app → support}/models/definition.rb +2 -0
  845. data/spec/support/models/delegating_patient.rb +15 -0
  846. data/spec/{app → support}/models/description.rb +2 -0
  847. data/spec/{app → support}/models/dictionary.rb +8 -0
  848. data/spec/{app → support}/models/division.rb +2 -0
  849. data/spec/{app → support}/models/doctor.rb +2 -0
  850. data/spec/{app → support}/models/dog.rb +2 -0
  851. data/spec/{app → support}/models/dokument.rb +2 -0
  852. data/spec/{app → support}/models/draft.rb +2 -0
  853. data/spec/{app → support}/models/dragon.rb +2 -0
  854. data/spec/{app → support}/models/driver.rb +3 -1
  855. data/spec/{app → support}/models/drug.rb +2 -0
  856. data/spec/{app → support}/models/dungeon.rb +2 -0
  857. data/spec/{app → support}/models/edit.rb +2 -0
  858. data/spec/{app → support}/models/email.rb +2 -0
  859. data/spec/{app → support}/models/employer.rb +2 -0
  860. data/spec/{app → support}/models/entry.rb +2 -0
  861. data/spec/support/models/eraser.rb +3 -0
  862. data/spec/{app → support}/models/even.rb +2 -0
  863. data/spec/{app → support}/models/event.rb +2 -0
  864. data/spec/{app → support}/models/exhibition.rb +2 -0
  865. data/spec/{app → support}/models/exhibitor.rb +2 -0
  866. data/spec/{app → support}/models/explosion.rb +2 -0
  867. data/spec/{app → support}/models/eye.rb +2 -0
  868. data/spec/{app → support}/models/eye_bowl.rb +2 -0
  869. data/spec/{app → support}/models/face.rb +2 -0
  870. data/spec/support/models/fanatic.rb +8 -0
  871. data/spec/{app → support}/models/favorite.rb +2 -0
  872. data/spec/{app → support}/models/filesystem.rb +2 -0
  873. data/spec/{app → support}/models/fire_hydrant.rb +2 -0
  874. data/spec/{app → support}/models/firefox.rb +2 -0
  875. data/spec/{app → support}/models/fish.rb +2 -0
  876. data/spec/{app → support}/models/folder.rb +2 -0
  877. data/spec/{app → support}/models/folder_item.rb +2 -0
  878. data/spec/{app → support}/models/fruits.rb +2 -0
  879. data/spec/{app → support}/models/game.rb +2 -0
  880. data/spec/{app → support}/models/ghost.rb +2 -0
  881. data/spec/support/models/guitar.rb +4 -0
  882. data/spec/support/models/hole.rb +12 -0
  883. data/spec/{app → support}/models/home.rb +2 -0
  884. data/spec/{app → support}/models/house.rb +2 -0
  885. data/spec/{app → support}/models/html_writer.rb +2 -0
  886. data/spec/{app → support}/models/id_key.rb +2 -0
  887. data/spec/support/models/idnodef.rb +7 -0
  888. data/spec/{app → support}/models/image.rb +2 -0
  889. data/spec/{app → support}/models/implant.rb +11 -0
  890. data/spec/support/models/instrument.rb +8 -0
  891. data/spec/{app → support}/models/item.rb +3 -1
  892. data/spec/{app → support}/models/jar.rb +2 -0
  893. data/spec/{app → support}/models/kaleidoscope.rb +2 -0
  894. data/spec/{app → support}/models/kangaroo.rb +3 -1
  895. data/spec/{app → support}/models/label.rb +6 -1
  896. data/spec/{app → support}/models/language.rb +2 -0
  897. data/spec/{app → support}/models/lat_lng.rb +2 -0
  898. data/spec/{app → support}/models/league.rb +2 -0
  899. data/spec/support/models/learner.rb +4 -0
  900. data/spec/{app → support}/models/line_item.rb +2 -0
  901. data/spec/{app → support}/models/location.rb +2 -0
  902. data/spec/{app → support}/models/login.rb +2 -0
  903. data/spec/{app → support}/models/manufacturer.rb +2 -0
  904. data/spec/{app → support}/models/meat.rb +2 -0
  905. data/spec/{app → support}/models/membership.rb +3 -0
  906. data/spec/{app → support}/models/message.rb +2 -0
  907. data/spec/{app → support}/models/minim.rb +0 -1
  908. data/spec/{app → support}/models/mixed_drink.rb +2 -0
  909. data/spec/support/models/mop.rb +24 -0
  910. data/spec/{app → support}/models/movie.rb +2 -0
  911. data/spec/support/models/my_hash.rb +4 -0
  912. data/spec/{app → support}/models/name.rb +2 -0
  913. data/spec/support/models/name_only.rb +8 -0
  914. data/spec/{app → support}/models/node.rb +2 -0
  915. data/spec/{app → support}/models/note.rb +2 -0
  916. data/spec/support/models/nut.rb +7 -0
  917. data/spec/{app → support}/models/odd.rb +2 -0
  918. data/spec/support/models/order.rb +12 -0
  919. data/spec/{app → support}/models/ordered_post.rb +3 -1
  920. data/spec/{app → support}/models/ordered_preference.rb +2 -0
  921. data/spec/{app → support}/models/oscar.rb +2 -0
  922. data/spec/support/models/other_owner_object.rb +4 -0
  923. data/spec/{app → support}/models/override.rb +2 -0
  924. data/spec/{app → support}/models/ownable.rb +2 -0
  925. data/spec/{app → support}/models/owner.rb +4 -0
  926. data/spec/{app → support}/models/pack.rb +2 -0
  927. data/spec/{app → support}/models/page.rb +2 -0
  928. data/spec/{app → support}/models/page_question.rb +2 -0
  929. data/spec/{app → support}/models/palette.rb +3 -1
  930. data/spec/{app → support}/models/parent.rb +2 -0
  931. data/spec/{app → support}/models/parent_doc.rb +2 -0
  932. data/spec/support/models/passport.rb +22 -0
  933. data/spec/{app → support}/models/patient.rb +2 -0
  934. data/spec/{app → support}/models/pdf_writer.rb +2 -0
  935. data/spec/support/models/pencil.rb +3 -0
  936. data/spec/{app → support}/models/person.rb +22 -1
  937. data/spec/{app → support}/models/pet.rb +2 -0
  938. data/spec/{app → support}/models/pet_owner.rb +2 -0
  939. data/spec/{app → support}/models/phone.rb +5 -1
  940. data/spec/support/models/piano.rb +4 -0
  941. data/spec/{app → support}/models/pizza.rb +2 -0
  942. data/spec/{app → support}/models/player.rb +4 -0
  943. data/spec/{app → support}/models/post.rb +2 -0
  944. data/spec/{app → support}/models/post_genre.rb +2 -0
  945. data/spec/support/models/powerup.rb +25 -0
  946. data/spec/{app → support}/models/preference.rb +2 -0
  947. data/spec/{app → support}/models/princess.rb +2 -0
  948. data/spec/{app → support}/models/product.rb +3 -0
  949. data/spec/support/models/profile.rb +17 -0
  950. data/spec/{app → support}/models/pronunciation.rb +2 -0
  951. data/spec/{app → support}/models/pub.rb +2 -0
  952. data/spec/support/models/publication/encyclopedia.rb +11 -0
  953. data/spec/support/models/publication/review.rb +13 -0
  954. data/spec/support/models/publication.rb +4 -0
  955. data/spec/{app → support}/models/purchase.rb +2 -0
  956. data/spec/support/models/purchased_item.rb +10 -0
  957. data/spec/{app → support}/models/question.rb +2 -0
  958. data/spec/{app → support}/models/quiz.rb +2 -0
  959. data/spec/{app → support}/models/rating.rb +2 -0
  960. data/spec/{app → support}/models/record.rb +2 -0
  961. data/spec/{app → support}/models/registry.rb +3 -0
  962. data/spec/{app → support}/models/role.rb +2 -0
  963. data/spec/{app → support}/models/root_category.rb +2 -0
  964. data/spec/{app → support}/models/sandwich.rb +2 -0
  965. data/spec/{app → support}/models/scheduler.rb +2 -0
  966. data/spec/support/models/school.rb +14 -0
  967. data/spec/support/models/scribe.rb +7 -0
  968. data/spec/support/models/sealer.rb +7 -0
  969. data/spec/support/models/seat.rb +24 -0
  970. data/spec/{app → support}/models/seo.rb +2 -0
  971. data/spec/support/models/series.rb +7 -0
  972. data/spec/{app → support}/models/server.rb +2 -0
  973. data/spec/{app → support}/models/service.rb +2 -0
  974. data/spec/{app → support}/models/shape.rb +4 -2
  975. data/spec/{app → support}/models/shelf.rb +2 -0
  976. data/spec/support/models/shield.rb +18 -0
  977. data/spec/{app → support}/models/shipment_address.rb +2 -0
  978. data/spec/{app → support}/models/shipping_container.rb +2 -0
  979. data/spec/{app → support}/models/shipping_pack.rb +2 -0
  980. data/spec/support/models/shirt.rb +11 -0
  981. data/spec/{app → support}/models/shop.rb +2 -0
  982. data/spec/{app → support}/models/short_agent.rb +2 -0
  983. data/spec/{app → support}/models/short_quiz.rb +2 -0
  984. data/spec/{app → support}/models/simple.rb +2 -0
  985. data/spec/{app → support}/models/slave.rb +2 -0
  986. data/spec/{app → support}/models/song.rb +2 -0
  987. data/spec/{app → support}/models/sound.rb +2 -0
  988. data/spec/support/models/spacer.rb +7 -0
  989. data/spec/{app → support}/models/square.rb +2 -0
  990. data/spec/{app → support}/models/staff.rb +2 -0
  991. data/spec/{app → support}/models/store_as_dup_test1.rb +2 -0
  992. data/spec/{app → support}/models/store_as_dup_test2.rb +2 -0
  993. data/spec/{app → support}/models/strategy.rb +2 -0
  994. data/spec/support/models/student.rb +14 -0
  995. data/spec/{app → support}/models/sub_item.rb +2 -0
  996. data/spec/{app → support}/models/subscription.rb +2 -0
  997. data/spec/{app → support}/models/survey.rb +2 -0
  998. data/spec/{app → support}/models/symptom.rb +2 -0
  999. data/spec/support/models/system_role.rb +7 -0
  1000. data/spec/{app → support}/models/tag.rb +2 -0
  1001. data/spec/{app → support}/models/target.rb +2 -0
  1002. data/spec/{app → support}/models/template.rb +2 -0
  1003. data/spec/{app → support}/models/thing.rb +2 -0
  1004. data/spec/support/models/threadlocker.rb +7 -0
  1005. data/spec/{app → support}/models/title.rb +2 -0
  1006. data/spec/{app → support}/models/tool.rb +4 -2
  1007. data/spec/{app → support}/models/topping.rb +2 -0
  1008. data/spec/support/models/toy.rb +9 -0
  1009. data/spec/{app → support}/models/track.rb +2 -0
  1010. data/spec/{app → support}/models/translation.rb +2 -0
  1011. data/spec/{app → support}/models/tree.rb +2 -0
  1012. data/spec/support/models/truck.rb +7 -0
  1013. data/spec/{app → support}/models/user.rb +2 -0
  1014. data/spec/{app → support}/models/user_account.rb +2 -0
  1015. data/spec/{app → support}/models/validation_callback.rb +2 -0
  1016. data/spec/support/models/vehicle.rb +18 -0
  1017. data/spec/{app → support}/models/version.rb +2 -0
  1018. data/spec/{app → support}/models/vertex.rb +3 -1
  1019. data/spec/{app → support}/models/vet_visit.rb +2 -0
  1020. data/spec/{app → support}/models/video.rb +2 -0
  1021. data/spec/support/models/video_game.rb +3 -0
  1022. data/spec/support/models/washer.rb +7 -0
  1023. data/spec/support/models/weapon.rb +25 -0
  1024. data/spec/{app → support}/models/wiki_page.rb +3 -0
  1025. data/spec/{app → support}/models/word.rb +2 -0
  1026. data/spec/{app → support}/models/word_origin.rb +2 -0
  1027. data/spec/{app → support}/models/writer.rb +4 -2
  1028. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  1029. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  1030. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  1031. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1032. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  1033. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1034. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  1035. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1036. data/spec/support/schema_maps/schema_map_local.json +18 -0
  1037. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1038. data/spec/support/shared/time.rb +53 -0
  1039. data/spec/support/spec_config.rb +30 -5
  1040. data.tar.gz.sig +0 -0
  1041. metadata +1240 -742
  1042. metadata.gz.sig +0 -0
  1043. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  1044. data/lib/mongoid/errors/eager_load.rb +0 -22
  1045. data/lib/mongoid/errors/invalid_value.rb +0 -16
  1046. data/lib/mongoid/matchable/all.rb +0 -27
  1047. data/lib/mongoid/matchable/and.rb +0 -30
  1048. data/lib/mongoid/matchable/default.rb +0 -72
  1049. data/lib/mongoid/matchable/elem_match.rb +0 -34
  1050. data/lib/mongoid/matchable/eq.rb +0 -22
  1051. data/lib/mongoid/matchable/exists.rb +0 -23
  1052. data/lib/mongoid/matchable/gt.rb +0 -23
  1053. data/lib/mongoid/matchable/gte.rb +0 -23
  1054. data/lib/mongoid/matchable/in.rb +0 -24
  1055. data/lib/mongoid/matchable/lt.rb +0 -23
  1056. data/lib/mongoid/matchable/lte.rb +0 -23
  1057. data/lib/mongoid/matchable/ne.rb +0 -21
  1058. data/lib/mongoid/matchable/nin.rb +0 -22
  1059. data/lib/mongoid/matchable/nor.rb +0 -37
  1060. data/lib/mongoid/matchable/or.rb +0 -33
  1061. data/lib/mongoid/matchable/regexp.rb +0 -27
  1062. data/lib/mongoid/matchable/size.rb +0 -21
  1063. data/lib/support/ruby_version.rb +0 -26
  1064. data/spec/app/models/actress.rb +0 -2
  1065. data/spec/app/models/augmentation.rb +0 -11
  1066. data/spec/app/models/bed.rb +0 -1
  1067. data/spec/app/models/car.rb +0 -1
  1068. data/spec/app/models/circus.rb +0 -7
  1069. data/spec/app/models/eraser.rb +0 -1
  1070. data/spec/app/models/learner.rb +0 -2
  1071. data/spec/app/models/my_hash.rb +0 -2
  1072. data/spec/app/models/other_owner_object.rb +0 -2
  1073. data/spec/app/models/passport.rb +0 -5
  1074. data/spec/app/models/pencil.rb +0 -1
  1075. data/spec/app/models/powerup.rb +0 -11
  1076. data/spec/app/models/profile.rb +0 -5
  1077. data/spec/app/models/series.rb +0 -4
  1078. data/spec/app/models/truck.rb +0 -3
  1079. data/spec/app/models/vehicle.rb +0 -11
  1080. data/spec/app/models/video_game.rb +0 -1
  1081. data/spec/app/models/weapon.rb +0 -11
  1082. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -58
  1083. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -58
  1084. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  1085. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1086. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1087. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1088. data/spec/mongoid/matchable/elem_match_spec.rb +0 -106
  1089. data/spec/mongoid/matchable/eq_spec.rb +0 -48
  1090. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1091. data/spec/mongoid/matchable/gt_spec.rb +0 -86
  1092. data/spec/mongoid/matchable/gte_spec.rb +0 -84
  1093. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1094. data/spec/mongoid/matchable/lt_spec.rb +0 -85
  1095. data/spec/mongoid/matchable/lte_spec.rb +0 -85
  1096. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1097. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1098. data/spec/mongoid/matchable/nor_spec.rb +0 -209
  1099. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1100. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1101. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1102. data/spec/mongoid/matchable_spec.rb +0 -853
  1103. data/spec/support/cluster_config.rb +0 -158
  1104. /data/spec/{app → support}/models/array_field.rb +0 -0
  1105. /data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  1106. /data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  1107. /data/spec/{app → support}/models/updatable.rb +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Mongoid::Criteria do
@@ -38,7 +40,7 @@ describe Mongoid::Criteria do
38
40
  context "when the entries are the same" do
39
41
 
40
42
  let!(:band) do
41
- Band.create(name: "Depeche Mode")
43
+ Band.create!(name: "Depeche Mode")
42
44
  end
43
45
 
44
46
  let(:other) do
@@ -53,11 +55,11 @@ describe Mongoid::Criteria do
53
55
  context "when the entries are not the same" do
54
56
 
55
57
  let!(:band) do
56
- Band.create(name: "Depeche Mode")
58
+ Band.create!(name: "Depeche Mode")
57
59
  end
58
60
 
59
61
  let!(:other_band) do
60
- Band.create(name: "Tool")
62
+ Band.create!(name: "Tool")
61
63
  end
62
64
 
63
65
  let(:other) do
@@ -102,21 +104,21 @@ describe Mongoid::Criteria do
102
104
  describe "#asc" do
103
105
 
104
106
  let(:person) do
105
- Person.create
107
+ Person.create!
106
108
  end
107
109
 
108
110
  context "when the documents are embedded" do
109
111
 
110
112
  let!(:hobrecht) do
111
- person.addresses.create(street: "hobrecht", name: "hobrecht")
113
+ person.addresses.create!(street: "hobrecht", name: "hobrecht")
112
114
  end
113
115
 
114
116
  let!(:friedel) do
115
- person.addresses.create(street: "friedel", name: "friedel")
117
+ person.addresses.create!(street: "friedel", name: "friedel")
116
118
  end
117
119
 
118
120
  let!(:pfluger) do
119
- person.addresses.create(street: "pfluger", name: "pfluger")
121
+ person.addresses.create!(street: "pfluger", name: "pfluger")
120
122
  end
121
123
 
122
124
  let(:criteria) do
@@ -132,7 +134,7 @@ describe Mongoid::Criteria do
132
134
  describe "#batch_size" do
133
135
 
134
136
  let(:person) do
135
- Person.create
137
+ Person.create!
136
138
  end
137
139
 
138
140
  let(:criteria) do
@@ -151,7 +153,7 @@ describe Mongoid::Criteria do
151
153
  describe "#read" do
152
154
 
153
155
  let(:person) do
154
- Person.create
156
+ Person.create!
155
157
  end
156
158
 
157
159
  let(:criteria) do
@@ -168,11 +170,11 @@ describe Mongoid::Criteria do
168
170
  context "when provided a single field" do
169
171
 
170
172
  let!(:depeche) do
171
- Band.create(name: "Depeche Mode", likes: 1000)
173
+ Band.create!(name: "Depeche Mode", likes: 1000)
172
174
  end
173
175
 
174
176
  let!(:tool) do
175
- Band.create(name: "Tool", likes: 500)
177
+ Band.create!(name: "Tool", likes: 500)
176
178
  end
177
179
 
178
180
  let(:criteria) do
@@ -210,11 +212,11 @@ describe Mongoid::Criteria do
210
212
  context "when provided a single field" do
211
213
 
212
214
  let!(:depeche) do
213
- Band.create(name: "Depeche Mode", likes: 1000)
215
+ Band.create!(name: "Depeche Mode", likes: 1000)
214
216
  end
215
217
 
216
218
  let!(:tool) do
217
- Band.create(name: "Tool", likes: 500)
219
+ Band.create!(name: "Tool", likes: 500)
218
220
  end
219
221
 
220
222
  let(:criteria) do
@@ -236,11 +238,11 @@ describe Mongoid::Criteria do
236
238
  describe "\##{method}" do
237
239
 
238
240
  let!(:match) do
239
- Band.create(genres: [ "electro", "dub" ])
241
+ Band.create!(genres: [ "electro", "dub" ])
240
242
  end
241
243
 
242
244
  let!(:non_match) do
243
- Band.create(genres: [ "house" ])
245
+ Band.create!(genres: [ "house" ])
244
246
  end
245
247
 
246
248
  let(:criteria) do
@@ -258,11 +260,11 @@ describe Mongoid::Criteria do
258
260
  describe "\##{method}" do
259
261
 
260
262
  let!(:match) do
261
- Band.create(name: "Depeche Mode", genres: [ "electro" ])
263
+ Band.create!(name: "Depeche Mode", genres: [ "electro" ])
262
264
  end
263
265
 
264
266
  let!(:non_match) do
265
- Band.create(genres: [ "house" ])
267
+ Band.create!(genres: [ "house" ])
266
268
  end
267
269
 
268
270
  let(:criteria) do
@@ -278,7 +280,7 @@ describe Mongoid::Criteria do
278
280
  describe "#as_json" do
279
281
 
280
282
  let!(:band) do
281
- Band.create(name: "Depeche Mode")
283
+ Band.create!(name: "Depeche Mode")
282
284
  end
283
285
 
284
286
  let(:criteria) do
@@ -308,11 +310,11 @@ describe Mongoid::Criteria do
308
310
  describe "#between" do
309
311
 
310
312
  let!(:match) do
311
- Band.create(member_count: 3)
313
+ Band.create!(member_count: 3)
312
314
  end
313
315
 
314
316
  let!(:non_match) do
315
- Band.create(member_count: 10)
317
+ Band.create!(member_count: 10)
316
318
  end
317
319
 
318
320
  let(:criteria) do
@@ -378,13 +380,14 @@ describe Mongoid::Criteria do
378
380
  describe "#cache" do
379
381
 
380
382
  let!(:person) do
381
- Person.create
383
+ Person.create!
382
384
  end
383
385
 
384
- context "when no eager loading is involved" do
386
+ context "when the query cache is enabled" do
387
+ query_cache_enabled
385
388
 
386
389
  let(:criteria) do
387
- Person.all.cache
390
+ Person.all
388
391
  end
389
392
 
390
393
  before do
@@ -392,17 +395,19 @@ describe Mongoid::Criteria do
392
395
  end
393
396
 
394
397
  it "does not hit the database after first iteration" do
395
- expect(criteria.context.view).to receive(:each).never
396
- criteria.each do |doc|
397
- expect(doc).to eq(person)
398
+ expect_no_queries do
399
+ criteria.each do |doc|
400
+ expect(doc).to eq(person)
401
+ end
398
402
  end
399
403
  end
400
404
  end
401
405
 
402
406
  context "when the criteria is eager loading" do
407
+ query_cache_enabled
403
408
 
404
409
  let(:criteria) do
405
- Person.includes(:posts).cache
410
+ Person.includes(:posts)
406
411
  end
407
412
 
408
413
  before do
@@ -410,9 +415,10 @@ describe Mongoid::Criteria do
410
415
  end
411
416
 
412
417
  it "does not hit the database after first iteration" do
413
- expect(criteria.context.view).to receive(:each).never
414
- criteria.each do |doc|
415
- expect(doc).to eq(person)
418
+ expect_no_queries do
419
+ criteria.each do |doc|
420
+ expect(doc).to eq(person)
421
+ end
416
422
  end
417
423
  end
418
424
  end
@@ -489,17 +495,6 @@ describe Mongoid::Criteria do
489
495
  end
490
496
  end
491
497
 
492
- describe "#cache" do
493
-
494
- let(:criteria) do
495
- Band.where(name: "Depeche Mode")
496
- end
497
-
498
- it "sets the cache option to true" do
499
- expect(criteria.cache).to be_cached
500
- end
501
- end
502
-
503
498
  describe "#context" do
504
499
 
505
500
  context "when the model is embedded" do
@@ -530,11 +525,11 @@ describe Mongoid::Criteria do
530
525
  describe "#delete" do
531
526
 
532
527
  let(:depeche) do
533
- Band.create(name: "Depeche Mode")
528
+ Band.create!(name: "Depeche Mode")
534
529
  end
535
530
 
536
531
  let(:tool) do
537
- Band.create(name: "Tool")
532
+ Band.create!(name: "Tool")
538
533
  end
539
534
 
540
535
  context "when no selector is provided" do
@@ -588,7 +583,7 @@ describe Mongoid::Criteria do
588
583
  describe "#each" do
589
584
 
590
585
  let!(:band) do
591
- Band.create(name: "Depeche Mode")
586
+ Band.create!(name: "Depeche Mode")
592
587
  end
593
588
 
594
589
  context "when provided a block" do
@@ -608,14 +603,14 @@ describe Mongoid::Criteria do
608
603
  describe "#elem_match" do
609
604
 
610
605
  let!(:match) do
611
- Band.create(name: "Depeche Mode").tap do |band|
606
+ Band.create!(name: "Depeche Mode").tap do |band|
612
607
  r = band.records
613
- r.create(name: "101")
608
+ r.create!(name: "101")
614
609
  end
615
610
  end
616
611
 
617
612
  let!(:non_match) do
618
- Band.create(genres: [ "house" ])
613
+ Band.create!(genres: [ "house" ])
619
614
  end
620
615
 
621
616
  let(:criteria) do
@@ -661,7 +656,7 @@ describe Mongoid::Criteria do
661
656
  context "when matching documents exist" do
662
657
 
663
658
  let!(:match) do
664
- Band.create(name: "Depeche Mode")
659
+ Band.create!(name: "Depeche Mode")
665
660
  end
666
661
 
667
662
  let(:criteria) do
@@ -676,7 +671,7 @@ describe Mongoid::Criteria do
676
671
  context "when no matching documents exist" do
677
672
 
678
673
  let!(:nonmatch) do
679
- Band.create(name: "New Order")
674
+ Band.create!(name: "New Order")
680
675
  end
681
676
 
682
677
  let(:criteria) do
@@ -692,11 +687,11 @@ describe Mongoid::Criteria do
692
687
  describe "#exists" do
693
688
 
694
689
  let!(:match) do
695
- Band.create(name: "Depeche Mode")
690
+ Band.create!(name: "Depeche Mode")
696
691
  end
697
692
 
698
693
  let!(:non_match) do
699
- Band.create
694
+ Band.create!
700
695
  end
701
696
 
702
697
  let(:criteria) do
@@ -713,7 +708,7 @@ describe Mongoid::Criteria do
713
708
  context "when matching documents exist" do
714
709
 
715
710
  let!(:match) do
716
- Band.create(name: "Depeche Mode")
711
+ Band.create!(name: "Depeche Mode")
717
712
  end
718
713
 
719
714
  let(:criteria) do
@@ -783,23 +778,83 @@ describe Mongoid::Criteria do
783
778
 
784
779
  describe "#field_list" do
785
780
 
781
+ context "when using the default discriminator key" do
782
+ let(:criteria) do
783
+ Doctor.only(:_id)
784
+ end
785
+
786
+ it "returns the fields with required _id minus type" do
787
+ expect(criteria.field_list).to eq([ "_id" ])
788
+ end
789
+ end
790
+
791
+ context "when using a custom discriminator key" do
792
+ before do
793
+ Person.discriminator_key = "dkey"
794
+ end
795
+
796
+ after do
797
+ Person.discriminator_key = nil
798
+ end
799
+
800
+ let(:criteria) do
801
+ Doctor.only(:_id, :_type)
802
+ end
803
+
804
+ it "returns the fields with type without dkey" do
805
+ expect(criteria.field_list).to eq([ "_id", "_type" ])
806
+ end
807
+ end
808
+ end
809
+
810
+ describe "#find" do
811
+ let!(:depeche) do
812
+ Band.create!(name: "Depeche Mode")
813
+ end
814
+
786
815
  let(:criteria) do
787
- Band.only(:name)
816
+ Band.where(name: "Depeche Mode")
817
+ end
818
+
819
+ context "when given a block" do
820
+ it "behaves as Enumerable" do
821
+ result = criteria.find { |c| c.name == "Depeche Mode" }
822
+ expect(result).to eq(depeche)
823
+ end
824
+ end
825
+
826
+ context "when given a Proc and a block" do
827
+ it "behaves as Enumerable" do
828
+ result = criteria.find(-> {"default"}) { |c| c.name == "Not Depeche Mode" }
829
+ expect(result).to eq("default")
830
+ end
831
+ end
832
+
833
+ context "when given a Proc without a block" do
834
+ it "raises an error" do
835
+ lambda do
836
+ criteria.find(-> {"default"})
837
+ # Proc is not serializable to a BSON type
838
+ end.should raise_error(BSON::Error::UnserializableClass)
839
+ end
788
840
  end
789
841
 
790
- it "returns the fields with required _id minus type" do
791
- expect(criteria.field_list).to eq([ "_id", "name" ])
842
+ context "when given an id" do
843
+ it "behaves as Findable" do
844
+ result = criteria.find(depeche.id)
845
+ expect(result).to eq(depeche)
846
+ end
792
847
  end
793
848
  end
794
849
 
795
850
  describe "#find_one_and_update" do
796
851
 
797
852
  let!(:depeche) do
798
- Band.create(name: "Depeche Mode")
853
+ Band.create!(name: "Depeche Mode")
799
854
  end
800
855
 
801
856
  let!(:tool) do
802
- Band.create(name: "Tool")
857
+ Band.create!(name: "Tool")
803
858
  end
804
859
 
805
860
  context "when the selector matches" do
@@ -938,7 +993,7 @@ describe Mongoid::Criteria do
938
993
  it "deletes the document from the database" do
939
994
  expect {
940
995
  depeche.reload
941
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
996
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Band with id\(s\)/)
942
997
  end
943
998
  end
944
999
  end
@@ -997,7 +1052,7 @@ describe Mongoid::Criteria do
997
1052
  end
998
1053
 
999
1054
  let!(:match) do
1000
- Bar.create(location: [ 52.30, 13.25 ])
1055
+ Bar.create!(location: [ 52.30, 13.25 ])
1001
1056
  end
1002
1057
 
1003
1058
  let(:criteria) do
@@ -1009,7 +1064,7 @@ describe Mongoid::Criteria do
1009
1064
  end
1010
1065
  end
1011
1066
 
1012
- describe "#gt" do
1067
+ describe "#eq" do
1013
1068
 
1014
1069
  let!(:match) do
1015
1070
  Band.create(member_count: 5)
@@ -1019,6 +1074,25 @@ describe Mongoid::Criteria do
1019
1074
  Band.create(member_count: 1)
1020
1075
  end
1021
1076
 
1077
+ let(:criteria) do
1078
+ Band.eq(member_count: 5)
1079
+ end
1080
+
1081
+ it "returns the matching documents" do
1082
+ expect(criteria).to eq([ match ])
1083
+ end
1084
+ end
1085
+
1086
+ describe "#gt" do
1087
+
1088
+ let!(:match) do
1089
+ Band.create!(member_count: 5)
1090
+ end
1091
+
1092
+ let!(:non_match) do
1093
+ Band.create!(member_count: 1)
1094
+ end
1095
+
1022
1096
  let(:criteria) do
1023
1097
  Band.gt(member_count: 4)
1024
1098
  end
@@ -1031,11 +1105,11 @@ describe Mongoid::Criteria do
1031
1105
  describe "#gte" do
1032
1106
 
1033
1107
  let!(:match) do
1034
- Band.create(member_count: 5)
1108
+ Band.create!(member_count: 5)
1035
1109
  end
1036
1110
 
1037
1111
  let!(:non_match) do
1038
- Band.create(member_count: 1)
1112
+ Band.create!(member_count: 1)
1039
1113
  end
1040
1114
 
1041
1115
  let(:criteria) do
@@ -1054,11 +1128,11 @@ describe Mongoid::Criteria do
1054
1128
  context "when querying on a normal field" do
1055
1129
 
1056
1130
  let!(:match) do
1057
- Band.create(genres: [ "electro", "dub" ])
1131
+ Band.create!(genres: [ "electro", "dub" ])
1058
1132
  end
1059
1133
 
1060
1134
  let!(:non_match) do
1061
- Band.create(genres: [ "house" ])
1135
+ Band.create!(genres: [ "house" ])
1062
1136
  end
1063
1137
 
1064
1138
  let(:criteria) do
@@ -1077,7 +1151,7 @@ describe Mongoid::Criteria do
1077
1151
  end
1078
1152
 
1079
1153
  let!(:match_one) do
1080
- Person.create(preference_ids: [ id ])
1154
+ Person.create!(preference_ids: [ id ])
1081
1155
  end
1082
1156
 
1083
1157
  context "when providing valid ids" do
@@ -1118,7 +1192,7 @@ describe Mongoid::Criteria do
1118
1192
  context "when the relation is a one to one" do
1119
1193
 
1120
1194
  let!(:game) do
1121
- Game.create
1195
+ Game.create!
1122
1196
  end
1123
1197
 
1124
1198
  let(:criteria) do
@@ -1153,1312 +1227,204 @@ describe Mongoid::Criteria do
1153
1227
  end
1154
1228
  end
1155
1229
 
1156
- describe "#includes" do
1230
+ describe "#lt" do
1157
1231
 
1158
- let!(:person) do
1159
- Person.create(age: 1)
1232
+ let!(:match) do
1233
+ Band.create!(member_count: 1)
1160
1234
  end
1161
1235
 
1162
- context "when providing a name that is not a relation" do
1163
-
1164
- it "raises an error" do
1165
- expect {
1166
- Person.includes(:members)
1167
- }.to raise_error(Mongoid::Errors::InvalidIncludes)
1168
- end
1236
+ let!(:non_match) do
1237
+ Band.create!(member_count: 5)
1169
1238
  end
1170
1239
 
1171
- context "when providing one association" do
1172
-
1173
- let!(:user) do
1174
- User.create(posts: [ post1 ])
1175
- end
1176
-
1177
- let!(:post1) do
1178
- Post.create
1179
- end
1180
-
1181
- let(:result) do
1182
- User.includes(:posts).first
1183
- end
1184
-
1185
- it "executes the query" do
1186
- expect(result).to eq(user)
1187
- end
1188
-
1189
- it "includes the related objects" do
1190
- expect(result.posts).to eq([ post1 ])
1191
- end
1240
+ let(:criteria) do
1241
+ Band.lt(member_count: 4)
1192
1242
  end
1193
1243
 
1194
- context "when providing a list of associations" do
1195
-
1196
- let!(:user) do
1197
- User.create(posts: [ post1 ], descriptions: [ description1 ])
1198
- end
1199
-
1200
- let!(:post1) do
1201
- Post.create
1202
- end
1203
-
1204
- let!(:description1) do
1205
- Description.create(details: 1)
1206
- end
1244
+ it "returns the matching documents" do
1245
+ expect(criteria).to eq([ match ])
1246
+ end
1247
+ end
1207
1248
 
1208
- let(:result) do
1209
- User.includes(:posts, :descriptions).first
1210
- end
1249
+ describe "#lte" do
1211
1250
 
1212
- it "executes the query" do
1213
- expect(result).to eq(user)
1214
- end
1251
+ let!(:match) do
1252
+ Band.create!(member_count: 4)
1253
+ end
1215
1254
 
1216
- it "includes the related objects" do
1217
- expect(result.posts).to eq([ post1 ])
1218
- expect(result.descriptions).to eq([ description1 ])
1219
- end
1255
+ let!(:non_match) do
1256
+ Band.create!(member_count: 5)
1220
1257
  end
1221
1258
 
1222
- context "when providing a nested association" do
1259
+ let(:criteria) do
1260
+ Band.lte(member_count: 4)
1261
+ end
1223
1262
 
1224
- let!(:user) do
1225
- User.create
1226
- end
1263
+ it "returns the matching documents" do
1264
+ expect(criteria).to eq([ match ])
1265
+ end
1266
+ end
1227
1267
 
1228
- before do
1229
- p = Post.create(alerts: [ Alert.create ])
1230
- user.posts = [ p ]
1231
- user.save
1232
- end
1268
+ describe "#map_reduce" do
1233
1269
 
1234
- let(:result) do
1235
- User.includes(:posts => [:alerts]).first
1236
- end
1270
+ let(:map) do
1271
+ %Q{
1272
+ function() {
1273
+ emit(this.name, { likes: this.likes });
1274
+ }}
1275
+ end
1237
1276
 
1238
- it "executes the query" do
1239
- expect(result).to eq(user)
1240
- end
1277
+ let(:reduce) do
1278
+ %Q{
1279
+ function(key, values) {
1280
+ var result = { likes: 0 };
1281
+ values.forEach(function(value) {
1282
+ result.likes += value.likes;
1283
+ });
1284
+ return result;
1285
+ }}
1286
+ end
1241
1287
 
1242
- it "includes the related objects" do
1243
- expect(result.posts.size).to eq(1)
1244
- expect(result.posts.first.alerts.size).to eq(1)
1245
- end
1288
+ let!(:depeche_mode) do
1289
+ Band.create!(name: "Depeche Mode", likes: 200)
1246
1290
  end
1247
1291
 
1248
- context "when providing a deeply nested association" do
1292
+ let!(:tool) do
1293
+ Band.create!(name: "Tool", likes: 100)
1294
+ end
1249
1295
 
1250
- let!(:user) do
1251
- User.create
1252
- end
1296
+ context "when no timeout options are provided" do
1253
1297
 
1254
- let(:results) do
1255
- User.includes(:posts => [{ :alerts => :items }]).to_a
1298
+ let(:map_reduce) do
1299
+ Band.limit(2).map_reduce(map, reduce).out(inline: 1)
1256
1300
  end
1257
1301
 
1258
- it "executes the query" do
1259
- expect(results.first).to eq(user)
1302
+ it "returns the map/reduce results" do
1303
+ expect(map_reduce.sort_by { |doc| doc['_id'] }).to eq([
1304
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
1305
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
1306
+ ])
1260
1307
  end
1261
1308
  end
1309
+ end
1262
1310
 
1263
- context "when the models are inherited" do
1311
+ describe "#max" do
1264
1312
 
1265
- before(:all) do
1266
- class A
1267
- include Mongoid::Document
1268
- end
1313
+ context "when provided a single field" do
1269
1314
 
1270
- class B < A
1271
- belongs_to :c
1272
- end
1315
+ let!(:depeche) do
1316
+ Band.create!(name: "Depeche Mode", likes: 1000)
1317
+ end
1273
1318
 
1274
- class C
1275
- include Mongoid::Document
1276
- has_one :b
1277
- end
1319
+ let!(:tool) do
1320
+ Band.create!(name: "Tool", likes: 500)
1278
1321
  end
1279
1322
 
1280
- after(:all) do
1281
- Object.send(:remove_const, :A)
1282
- Object.send(:remove_const, :B)
1283
- Object.send(:remove_const, :C)
1323
+ let(:criteria) do
1324
+ Band.all
1284
1325
  end
1285
1326
 
1286
- context "when the includes is on the subclass" do
1327
+ context "when provided a symbol" do
1287
1328
 
1288
- let!(:c_one) do
1289
- C.create
1329
+ let(:max) do
1330
+ criteria.max(:likes)
1290
1331
  end
1291
1332
 
1292
- let!(:c_two) do
1293
- C.create
1333
+ it "returns the max of the provided field" do
1334
+ expect(max).to eq(1000)
1294
1335
  end
1336
+ end
1295
1337
 
1296
- let!(:b) do
1297
- B.create(c: c_two)
1298
- end
1338
+ context "when provided a block" do
1299
1339
 
1300
- let!(:results) do
1301
- C.includes(:b).to_a.detect do |c|
1302
- c.id == c_two.id
1340
+ let(:max) do
1341
+ criteria.max do |a, b|
1342
+ a.likes <=> b.likes
1303
1343
  end
1304
1344
  end
1305
1345
 
1306
- it "returns the correct documents" do
1307
- expect(results).to eq(c_two)
1308
- end
1309
-
1310
- it "does not query the db" do
1311
- expect_query(0) do
1312
- results.b
1313
- end
1346
+ it "returns the document with the max value for the field" do
1347
+ expect(max).to eq(depeche)
1314
1348
  end
1315
1349
  end
1316
1350
  end
1351
+ end
1317
1352
 
1318
- context "when the models are inherited from another one model" do
1353
+ describe "#max_distance" do
1319
1354
 
1320
- context "when the relation is a has_one" do
1355
+ before do
1356
+ Bar.create_indexes
1357
+ end
1321
1358
 
1322
- before(:all) do
1323
- class A
1324
- include Mongoid::Document
1325
- end
1359
+ let!(:match) do
1360
+ Bar.create!(location: [ 52.30, 13.25 ])
1361
+ end
1326
1362
 
1327
- class B < A
1328
- belongs_to :d
1329
- end
1363
+ let!(:non_match) do
1364
+ Bar.create!(location: [ 19.26, 99.70 ])
1365
+ end
1330
1366
 
1331
- class C < A
1332
- belongs_to :d
1333
- end
1367
+ let(:criteria) do
1368
+ Bar.near(location: [ 52, 13 ]).max_distance(location: 5)
1369
+ end
1334
1370
 
1335
- class D
1336
- include Mongoid::Document
1337
- has_one :b
1338
- has_one :c
1339
- end
1340
- end
1371
+ it "returns the matching documents" do
1372
+ expect(criteria).to eq([ match ])
1373
+ end
1374
+ end
1341
1375
 
1342
- after(:all) do
1343
- Object.send(:remove_const, :A)
1344
- Object.send(:remove_const, :B)
1345
- Object.send(:remove_const, :C)
1346
- Object.send(:remove_const, :D)
1347
- end
1376
+ describe "#merge" do
1348
1377
 
1349
- context "when the includes is on the several relations" do
1378
+ let(:band) do
1379
+ Band.new
1380
+ end
1350
1381
 
1351
- let!(:d_one) do
1352
- D.create
1353
- end
1382
+ let(:criteria) do
1383
+ Band.scoped.where(name: "Depeche Mode").asc(:name)
1384
+ end
1354
1385
 
1355
- let!(:d_two) do
1356
- D.create
1357
- end
1386
+ context "when merging with another criteria" do
1358
1387
 
1359
- let!(:b) do
1360
- B.create(d: d_two)
1361
- end
1388
+ let(:mergeable) do
1389
+ Band.includes(:records).tap do |crit|
1390
+ crit.documents = [ band ]
1391
+ end
1392
+ end
1362
1393
 
1363
- let!(:c) do
1364
- C.create(d: d_two)
1365
- end
1394
+ let(:association) do
1395
+ Band.relations["records"]
1396
+ end
1366
1397
 
1367
- let!(:results) do
1368
- D.includes(:b, :c).entries.detect do |d|
1369
- d.id == d_two.id
1370
- end
1371
- end
1398
+ let(:merged) do
1399
+ criteria.merge(mergeable)
1400
+ end
1372
1401
 
1373
- it "returns the correct documents" do
1374
- expect(results).to eq(d_two)
1375
- end
1402
+ it "merges the selector" do
1403
+ expect(merged.selector).to eq({ "name" => "Depeche Mode" })
1404
+ end
1376
1405
 
1377
- it "does not query the db on b" do
1378
- expect_query(0) do
1379
- results.b
1380
- end
1381
- end
1406
+ it "merges the options" do
1407
+ expect(merged.options).to eq({ sort: { "name" => 1 }})
1408
+ end
1382
1409
 
1383
- it "does not query the db on c" do
1384
- expect_query(0) do
1385
- results.b
1386
- end
1387
- end
1388
- end
1410
+ it "merges the documents" do
1411
+ expect(merged.documents).to eq([ band ])
1389
1412
  end
1390
1413
 
1391
- context "when the relation is a has_many" do
1414
+ it "merges the scoping options" do
1415
+ expect(merged.scoping_options).to eq([ nil, nil ])
1416
+ end
1392
1417
 
1393
- before(:all) do
1394
- class A
1395
- include Mongoid::Document
1396
- end
1418
+ it "merges the inclusions" do
1419
+ expect(merged.inclusions).to eq([ association ])
1420
+ end
1397
1421
 
1398
- class B < A
1399
- belongs_to :d
1400
- end
1422
+ it "returns a new criteria" do
1423
+ expect(merged).to_not equal(criteria)
1424
+ end
1425
+ end
1401
1426
 
1402
- class C < A
1403
- belongs_to :d
1404
- end
1405
-
1406
- class D
1407
- include Mongoid::Document
1408
- has_many :b
1409
- has_many :c
1410
- end
1411
- end
1412
-
1413
- after(:all) do
1414
- Object.send(:remove_const, :A)
1415
- Object.send(:remove_const, :B)
1416
- Object.send(:remove_const, :C)
1417
- Object.send(:remove_const, :D)
1418
- end
1419
-
1420
- context "when the includes is on the several relations" do
1421
-
1422
- let!(:d_one) do
1423
- D.create
1424
- end
1425
-
1426
- let!(:d_two) do
1427
- D.create
1428
- end
1429
-
1430
- let!(:bs) do
1431
- 2.times.map { B.create(d: d_two) }
1432
- end
1433
-
1434
- let!(:cs) do
1435
- 2.times.map { C.create(d: d_two) }
1436
- end
1437
-
1438
- let!(:results) do
1439
- D.includes(:b, :c).entries.detect do |d|
1440
- d.id == d_two.id
1441
- end
1442
- end
1443
-
1444
- it "returns the correct documents" do
1445
- expect(results).to eq(d_two)
1446
- end
1447
-
1448
- it "does not query the db on b" do
1449
- expect_query(0) do
1450
- results.b
1451
- end
1452
- end
1453
-
1454
- it "does not query the db on c" do
1455
- expect_query(0) do
1456
- results.b
1457
- end
1458
- end
1459
- end
1460
- end
1461
- end
1462
-
1463
- context "when including the same association multiple times" do
1464
-
1465
- let(:criteria) do
1466
- Person.all.includes(:posts, :posts).includes(:posts)
1467
- end
1468
-
1469
- let(:association) do
1470
- Person.reflect_on_association(:posts)
1471
- end
1472
-
1473
- it "does not duplicate the association in the inclusions" do
1474
- expect(criteria.inclusions).to eq([ association ])
1475
- end
1476
- end
1477
-
1478
- context "when mapping the results more than once" do
1479
-
1480
- let!(:post) do
1481
- person.posts.create(title: "one")
1482
- end
1483
-
1484
- let(:criteria) do
1485
- Post.includes(:person)
1486
- end
1487
-
1488
- let!(:results) do
1489
- criteria.map { |doc| doc }
1490
- criteria.map { |doc| doc }
1491
- end
1492
-
1493
- it "returns the proper results" do
1494
- expect(results.first.title).to eq("one")
1495
- end
1496
- end
1497
-
1498
- context "when including a belongs to relation" do
1499
-
1500
- context "when the criteria is from the root" do
1501
-
1502
- let!(:person_two) do
1503
- Person.create(age: 2)
1504
- end
1505
-
1506
- let!(:post_one) do
1507
- person.posts.create(title: "one")
1508
- end
1509
-
1510
- let!(:post_two) do
1511
- person_two.posts.create(title: "two")
1512
- end
1513
-
1514
- context "when calling first" do
1515
-
1516
- let(:criteria) do
1517
- Post.includes(:person)
1518
- end
1519
-
1520
- let!(:document) do
1521
- criteria.first
1522
- end
1523
-
1524
- it "eager loads the first document" do
1525
- expect_query(0) do
1526
- expect(document.person).to eq(person)
1527
- end
1528
- end
1529
-
1530
- it "returns the first document" do
1531
- expect(document).to eq(post_one)
1532
- end
1533
- end
1534
-
1535
- context "when calling last" do
1536
-
1537
- let!(:criteria) do
1538
- Post.asc(:_id).includes(:person)
1539
- end
1540
-
1541
- let!(:document) do
1542
- criteria.last
1543
- end
1544
-
1545
- it "eager loads the last document" do
1546
- expect_query(0) do
1547
- expect(document.person).to eq(person_two)
1548
- end
1549
- end
1550
-
1551
- it "returns the last document" do
1552
- expect(document).to eq(post_two)
1553
- end
1554
- end
1555
- end
1556
-
1557
- context "when the criteria is from an embedded relation" do
1558
-
1559
- let(:peep) do
1560
- Person.create
1561
- end
1562
-
1563
- let!(:address_one) do
1564
- peep.addresses.create(street: "rosenthaler")
1565
- end
1566
-
1567
- let!(:address_two) do
1568
- peep.addresses.create(street: "weinmeister")
1569
- end
1570
-
1571
- let!(:depeche) do
1572
- Band.create!(name: "Depeche Mode")
1573
- end
1574
-
1575
- let!(:tool) do
1576
- Band.create!(name: "Tool")
1577
- end
1578
-
1579
- before do
1580
- address_one.band = depeche
1581
- address_two.band = tool
1582
- address_one.save
1583
- address_two.save
1584
- end
1585
-
1586
- context "when calling first" do
1587
-
1588
- let(:criteria) do
1589
- peep.reload.addresses.includes(:band)
1590
- end
1591
-
1592
- let(:context) do
1593
- criteria.context
1594
- end
1595
-
1596
- let!(:document) do
1597
- criteria.first
1598
- end
1599
-
1600
- it "eager loads the first document" do
1601
- expect_query(0) do
1602
- expect(document.band).to eq(depeche)
1603
- end
1604
- end
1605
-
1606
- it "returns the document" do
1607
- expect(document).to eq(address_one)
1608
- end
1609
- end
1610
-
1611
- context "when calling last" do
1612
-
1613
- let(:criteria) do
1614
- peep.reload.addresses.includes(:band)
1615
- end
1616
-
1617
- let(:context) do
1618
- criteria.context
1619
- end
1620
-
1621
- let!(:document) do
1622
- criteria.last
1623
- end
1624
-
1625
- it "eager loads the last document" do
1626
- expect_query(0) do
1627
- expect(document.band).to eq(tool)
1628
- end
1629
- end
1630
-
1631
- it "returns the document" do
1632
- expect(document).to eq(address_two)
1633
- end
1634
- end
1635
-
1636
- context "when iterating all documents" do
1637
-
1638
- let(:criteria) do
1639
- peep.reload.addresses.includes(:band)
1640
- end
1641
-
1642
- let(:context) do
1643
- criteria.context
1644
- end
1645
-
1646
- let!(:documents) do
1647
- criteria.to_a
1648
- end
1649
-
1650
- it "eager loads the first document" do
1651
- expect_query(0) do
1652
- expect(documents.first.band).to eq(depeche)
1653
- end
1654
- end
1655
-
1656
- it "eager loads the last document" do
1657
- expect_query(0) do
1658
- expect(documents.last.band).to eq(tool)
1659
- end
1660
- end
1661
-
1662
- it "returns the documents" do
1663
- expect(documents).to eq([ address_one, address_two ])
1664
- end
1665
- end
1666
- end
1667
- end
1668
-
1669
- context "when providing inclusions to the default scope" do
1670
-
1671
- before do
1672
- Person.default_scope(->{ Person.includes(:posts) })
1673
- end
1674
-
1675
- after do
1676
- Person.default_scoping = nil
1677
- end
1678
-
1679
- let!(:post_one) do
1680
- person.posts.create(title: "one")
1681
- end
1682
-
1683
- let!(:post_two) do
1684
- person.posts.create(title: "two")
1685
- end
1686
-
1687
- context "when the criteria has no options" do
1688
-
1689
- let!(:criteria) do
1690
- Person.asc(:age).all
1691
- end
1692
-
1693
- let!(:documents) do
1694
- criteria.entries
1695
- end
1696
-
1697
- it "returns the correct documents" do
1698
- expect(documents).to eq([ person ])
1699
- end
1700
-
1701
- it "eager loads the first document" do
1702
- expect_query(0) do
1703
- expect(documents.first.posts.first).to eq(post_one)
1704
- end
1705
- end
1706
-
1707
- it "eager loads the last document" do
1708
- expect_query(0) do
1709
- expect(documents.first.posts.last).to eq(post_two)
1710
- end
1711
- end
1712
-
1713
- context "when executing the query twice" do
1714
-
1715
- let!(:new_criteria) do
1716
- Person.where(id: person.id)
1717
- end
1718
-
1719
- let!(:new_context) do
1720
- new_criteria.context
1721
- end
1722
-
1723
- before do
1724
- expect(new_context).to receive(:eager_load).with([person]).once.and_call_original
1725
- end
1726
-
1727
- let!(:from_db) do
1728
- new_criteria.first
1729
- end
1730
-
1731
- it "does not duplicate documents in the relation" do
1732
- expect(person.posts.size).to eq(2)
1733
- end
1734
- end
1735
- end
1736
-
1737
- context "when calling first on the criteria" do
1738
-
1739
- let(:criteria) do
1740
- Person.asc(:age).all
1741
- end
1742
-
1743
- let!(:from_db) do
1744
- criteria.first
1745
- end
1746
-
1747
- it "returns the correct documents" do
1748
- expect(from_db).to eq(person)
1749
- end
1750
-
1751
- it "eager loads the first document" do
1752
- expect_query(0) do
1753
- expect(from_db.posts.first).to eq(post_one)
1754
- end
1755
- end
1756
-
1757
- it "eager loads the last document" do
1758
- expect_query(0) do
1759
- expect(from_db.posts.last).to eq(post_two)
1760
- end
1761
- end
1762
- end
1763
-
1764
- context "when calling last on the criteria" do
1765
-
1766
- let(:criteria) do
1767
- Person.asc(:age).all
1768
- end
1769
-
1770
- let!(:context) do
1771
- criteria.context
1772
- end
1773
-
1774
- before do
1775
- expect(context).to receive(:eager_load).with([person]).once.and_call_original
1776
- end
1777
-
1778
- let!(:from_db) do
1779
- criteria.last
1780
- end
1781
-
1782
- it "returns the correct documents" do
1783
- expect(from_db).to eq(person)
1784
- end
1785
-
1786
- it "eager loads the first document" do
1787
- expect_query(0) do
1788
- expect(from_db.posts.first).to eq(post_one)
1789
- end
1790
- end
1791
-
1792
- it "eager loads the last document" do
1793
- expect_query(0) do
1794
- expect(from_db.posts.last).to eq(post_two)
1795
- end
1796
- end
1797
- end
1798
-
1799
- context "when the criteria has limiting options" do
1800
-
1801
- let!(:person_two) do
1802
- Person.create
1803
- end
1804
-
1805
- let!(:post_three) do
1806
- person_two.posts.create(title: "three")
1807
- end
1808
-
1809
- let!(:criteria) do
1810
- Person.asc(:age).limit(1)
1811
- end
1812
-
1813
- let!(:documents) do
1814
- criteria.entries
1815
- end
1816
-
1817
- it "returns the correct documents" do
1818
- expect(criteria).to eq([ person ])
1819
- end
1820
-
1821
- it "eager loads the first document" do
1822
- expect_query(0) do
1823
- expect(documents.first.posts.first).to eq(post_one)
1824
- end
1825
- end
1826
-
1827
- it "eager loads the second document" do
1828
- expect_query(0) do
1829
- expect(documents.first.posts.last).to eq(post_two)
1830
- end
1831
- end
1832
- end
1833
- end
1834
-
1835
- context "when including a has and belongs to many" do
1836
-
1837
- let!(:preference_one) do
1838
- person.preferences.create(name: "one")
1839
- end
1840
-
1841
- let!(:preference_two) do
1842
- person.preferences.create(name: "two")
1843
- end
1844
-
1845
- context "when one of the related items is deleted" do
1846
-
1847
- before do
1848
- person.preferences = [ preference_one, preference_two ]
1849
- preference_two.delete
1850
- end
1851
-
1852
- let(:criteria) do
1853
- Person.where(id: person.id).includes(:preferences)
1854
- end
1855
-
1856
- it "only loads the existing related items" do
1857
- expect(criteria.entries.first.preferences).to eq([ preference_one ])
1858
- end
1859
- end
1860
-
1861
- context "when the criteria has no options" do
1862
-
1863
- let!(:criteria) do
1864
- Person.asc(:age).includes(:preferences)
1865
- end
1866
-
1867
- let!(:documents) do
1868
- criteria.entries
1869
- end
1870
-
1871
- it "returns the correct documents" do
1872
- expect(documents).to eq([ person ])
1873
- end
1874
-
1875
- it "eager loads the first document" do
1876
- expect_query(0) do
1877
- expect(documents.first.preferences.first).to eq(preference_one)
1878
- end
1879
- end
1880
-
1881
- it "eager loads the last document" do
1882
- expect_query(0) do
1883
- expect(documents.first.preferences.last).to eq(preference_two)
1884
- end
1885
- end
1886
- end
1887
-
1888
- context "when calling first on the criteria" do
1889
-
1890
- let!(:criteria) do
1891
- Person.asc(:age).includes(:preferences)
1892
- end
1893
-
1894
- let!(:from_db) do
1895
- criteria.first
1896
- end
1897
-
1898
- it "returns the correct documents" do
1899
- expect(from_db).to eq(person)
1900
- end
1901
-
1902
- it "eager loads the first document" do
1903
- expect_query(0) do
1904
- expect(from_db.preferences.first).to eq(preference_one)
1905
- end
1906
- end
1907
-
1908
- it "eager loads the last document" do
1909
- expect_query(0) do
1910
- expect(from_db.preferences.last).to eq(preference_two)
1911
- end
1912
- end
1913
- end
1914
-
1915
- context "when calling last on the criteria" do
1916
-
1917
- let!(:criteria) do
1918
- Person.asc(:age).includes(:preferences)
1919
- end
1920
-
1921
- let!(:from_db) do
1922
- criteria.last
1923
- end
1924
-
1925
- it "returns the correct documents" do
1926
- expect(from_db).to eq(person)
1927
- end
1928
-
1929
- it "eager loads the first document" do
1930
- expect_query(0) do
1931
- expect(from_db.preferences.first).to eq(preference_one)
1932
- end
1933
- end
1934
-
1935
- it "eager loads the last document" do
1936
- expect_query(0) do
1937
- expect(from_db.preferences.last).to eq(preference_two)
1938
- end
1939
- end
1940
- end
1941
- end
1942
-
1943
- context "when including a has many" do
1944
-
1945
- let!(:post_one) do
1946
- person.posts.create(title: "one")
1947
- end
1948
-
1949
- let!(:post_two) do
1950
- person.posts.create(title: "two")
1951
- end
1952
-
1953
- context "when the criteria has no options" do
1954
-
1955
- let!(:criteria) do
1956
- Person.asc(:age).includes(:posts)
1957
- end
1958
-
1959
- let!(:documents) do
1960
- criteria.entries
1961
- end
1962
-
1963
- it "returns the correct documents" do
1964
- expect(documents).to eq([ person ])
1965
- end
1966
-
1967
- it "eager loads the first document" do
1968
- expect_query(0) do
1969
- expect(documents.first.posts.first).to eq(post_one)
1970
- end
1971
- end
1972
-
1973
- it "eager loads the last document" do
1974
- expect_query(0) do
1975
- expect(documents.first.posts.last).to eq(post_two)
1976
- end
1977
- end
1978
- end
1979
-
1980
- context "when calling first on the criteria" do
1981
-
1982
- let!(:criteria) do
1983
- Person.asc(:age).includes(:posts)
1984
- end
1985
-
1986
- let!(:from_db) do
1987
- criteria.first
1988
- end
1989
-
1990
- it "returns the correct documents" do
1991
- expect(from_db).to eq(person)
1992
- end
1993
-
1994
- context "when subsequently getting all documents" do
1995
-
1996
- let!(:documents) do
1997
- criteria.entries
1998
- end
1999
-
2000
- it "returns the correct documents" do
2001
- expect(documents).to eq([ person ])
2002
- end
2003
- end
2004
- end
2005
-
2006
- context "when calling last on the criteria" do
2007
-
2008
- let!(:criteria) do
2009
- Person.asc(:age).includes(:posts)
2010
- end
2011
-
2012
- let!(:from_db) do
2013
- criteria.last
2014
- end
2015
-
2016
- it "returns the correct documents" do
2017
- expect(from_db).to eq(person)
2018
- end
2019
-
2020
- context "when subsequently getting all documents" do
2021
-
2022
- let!(:documents) do
2023
- criteria.entries
2024
- end
2025
-
2026
- it "returns the correct documents" do
2027
- expect(documents).to eq([ person ])
2028
- end
2029
- end
2030
- end
2031
-
2032
- context "when the criteria has limiting options" do
2033
-
2034
- let!(:person_two) do
2035
- Person.create
2036
- end
2037
-
2038
- let!(:post_three) do
2039
- person_two.posts.create(title: "three")
2040
- end
2041
-
2042
- let!(:criteria) do
2043
- Person.includes(:posts).asc(:age).limit(1)
2044
- end
2045
-
2046
- let(:context) do
2047
- criteria.context
2048
- end
2049
-
2050
- before do
2051
- expect(context).to receive(:eager_load).with([ person ]).once.and_call_original
2052
- end
2053
-
2054
- let!(:documents) do
2055
- criteria.entries
2056
- end
2057
-
2058
- it "returns the correct documents" do
2059
- expect(documents).to eq([ person ])
2060
- end
2061
- end
2062
- end
2063
-
2064
- context "when including a has one" do
2065
-
2066
- let!(:game_one) do
2067
- person.create_game(name: "one")
2068
- end
2069
-
2070
- let!(:game_two) do
2071
- person.create_game(name: "two")
2072
- end
2073
-
2074
- context "when the criteria has no options" do
2075
-
2076
- let!(:criteria) do
2077
- Person.asc(:age).includes(:game)
2078
- end
2079
-
2080
- let(:context) do
2081
- criteria.context
2082
- end
2083
-
2084
- before do
2085
- expect(context).to receive(:eager_load).with([ person ]).once.and_call_original
2086
- end
2087
-
2088
- let!(:documents) do
2089
- criteria.entries
2090
- end
2091
-
2092
- it "returns the correct documents" do
2093
- expect(documents).to eq([ person ])
2094
- end
2095
- end
2096
-
2097
- context "when the criteria has limiting options" do
2098
-
2099
- let!(:person_two) do
2100
- Person.create(age: 2)
2101
- end
2102
-
2103
- let!(:game_three) do
2104
- person_two.create_game(name: "Skyrim")
2105
- end
2106
-
2107
- let!(:criteria) do
2108
- Person.where(id: person.id).includes(:game).asc(:age).limit(1)
2109
- end
2110
-
2111
- let(:context) do
2112
- criteria.context
2113
- end
2114
-
2115
- before do
2116
- expect(context).to receive(:eager_load).with([ person ]).once.and_call_original
2117
- end
2118
-
2119
- let!(:documents) do
2120
- criteria.entries
2121
- end
2122
-
2123
- it "returns the correct documents" do
2124
- expect(documents).to eq([ person ])
2125
- end
2126
- end
2127
- end
2128
-
2129
- context "when including a belongs to" do
2130
-
2131
- let(:person_two) do
2132
- Person.create(age: 2)
2133
- end
2134
-
2135
- let!(:game_one) do
2136
- person.create_game(name: "one")
2137
- end
2138
-
2139
- let!(:game_two) do
2140
- person_two.create_game(name: "two")
2141
- end
2142
-
2143
- context "when providing no options" do
2144
-
2145
- let!(:criteria) do
2146
- Game.includes(:person)
2147
- end
2148
-
2149
- let(:context) do
2150
- criteria.context
2151
- end
2152
-
2153
- before do
2154
- expect(context).to receive(:preload).twice.and_call_original
2155
- end
2156
-
2157
- let!(:documents) do
2158
- criteria.entries
2159
- end
2160
-
2161
- it "returns the correct documents" do
2162
- expect(criteria).to eq([ game_one, game_two ])
2163
- end
2164
- end
2165
-
2166
- context "when the criteria has limiting options" do
2167
-
2168
- let!(:criteria) do
2169
- Game.where(id: game_one.id).includes(:person).asc(:_id).limit(1)
2170
- end
2171
-
2172
- let(:context) do
2173
- criteria.context
2174
- end
2175
-
2176
- before do
2177
- expect(context).to receive(:eager_load).with([ game_one ]).once.and_call_original
2178
- end
2179
-
2180
- let!(:documents) do
2181
- criteria.entries
2182
- end
2183
-
2184
- it "returns the correct documents" do
2185
- expect(documents).to eq([ game_one ])
2186
- end
2187
- end
2188
- end
2189
-
2190
- context "when including multiples in the same criteria" do
2191
-
2192
- let!(:post_one) do
2193
- person.posts.create(title: "one")
2194
- end
2195
-
2196
- let!(:post_two) do
2197
- person.posts.create(title: "two")
2198
- end
2199
-
2200
- let!(:game_one) do
2201
- person.create_game(name: "one")
2202
- end
2203
-
2204
- let!(:game_two) do
2205
- person.create_game(name: "two")
2206
- end
2207
-
2208
- let!(:criteria) do
2209
- Person.includes(:posts, :game).asc(:age)
2210
- end
2211
-
2212
- let(:context) do
2213
- criteria.context
2214
- end
2215
-
2216
- before do
2217
- expect(context).to receive(:preload).twice.and_call_original
2218
- end
2219
-
2220
- let!(:documents) do
2221
- criteria.entries
2222
- end
2223
-
2224
- it "returns the correct documents" do
2225
- expect(criteria).to eq([ person ])
2226
- end
2227
- end
2228
- end
2229
-
2230
- describe "#inclusions" do
2231
-
2232
- let(:criteria) do
2233
- Band.includes(:records)
2234
- end
2235
-
2236
- let(:association) do
2237
- Band.relations["records"]
2238
- end
2239
-
2240
- it "returns the inclusions" do
2241
- expect(criteria.inclusions).to eq([ association ])
2242
- end
2243
- end
2244
-
2245
- describe "#inclusions=" do
2246
-
2247
- let(:criteria) do
2248
- Band.all
2249
- end
2250
-
2251
- let(:association) do
2252
- Band.relations["records"]
2253
- end
2254
-
2255
- before do
2256
- criteria.inclusions = [ association ]
2257
- end
2258
-
2259
- it "sets the inclusions" do
2260
- expect(criteria.inclusions).to eq([ association ])
2261
- end
2262
- end
2263
-
2264
- describe "#lt" do
2265
-
2266
- let!(:match) do
2267
- Band.create(member_count: 1)
2268
- end
2269
-
2270
- let!(:non_match) do
2271
- Band.create(member_count: 5)
2272
- end
2273
-
2274
- let(:criteria) do
2275
- Band.lt(member_count: 4)
2276
- end
2277
-
2278
- it "returns the matching documents" do
2279
- expect(criteria).to eq([ match ])
2280
- end
2281
- end
2282
-
2283
- describe "#lte" do
2284
-
2285
- let!(:match) do
2286
- Band.create(member_count: 4)
2287
- end
2288
-
2289
- let!(:non_match) do
2290
- Band.create(member_count: 5)
2291
- end
2292
-
2293
- let(:criteria) do
2294
- Band.lte(member_count: 4)
2295
- end
2296
-
2297
- it "returns the matching documents" do
2298
- expect(criteria).to eq([ match ])
2299
- end
2300
- end
2301
-
2302
- describe "#map_reduce" do
2303
-
2304
- let(:map) do
2305
- %Q{
2306
- function() {
2307
- emit(this.name, { likes: this.likes });
2308
- }}
2309
- end
2310
-
2311
- let(:reduce) do
2312
- %Q{
2313
- function(key, values) {
2314
- var result = { likes: 0 };
2315
- values.forEach(function(value) {
2316
- result.likes += value.likes;
2317
- });
2318
- return result;
2319
- }}
2320
- end
2321
-
2322
- let!(:depeche_mode) do
2323
- Band.create(name: "Depeche Mode", likes: 200)
2324
- end
2325
-
2326
- let!(:tool) do
2327
- Band.create(name: "Tool", likes: 100)
2328
- end
2329
-
2330
- context "when no timeout options are provided" do
2331
-
2332
- let(:map_reduce) do
2333
- Band.limit(2).map_reduce(map, reduce).out(inline: 1)
2334
- end
2335
-
2336
- it "returns the map/reduce results" do
2337
- expect(map_reduce).to eq([
2338
- { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
2339
- { "_id" => "Tool", "value" => { "likes" => 100 }}
2340
- ])
2341
- end
2342
- end
2343
- end
2344
-
2345
- describe "#max" do
2346
-
2347
- context "when provided a single field" do
2348
-
2349
- let!(:depeche) do
2350
- Band.create(name: "Depeche Mode", likes: 1000)
2351
- end
2352
-
2353
- let!(:tool) do
2354
- Band.create(name: "Tool", likes: 500)
2355
- end
2356
-
2357
- let(:criteria) do
2358
- Band.all
2359
- end
2360
-
2361
- context "when provided a symbol" do
2362
-
2363
- let(:max) do
2364
- criteria.max(:likes)
2365
- end
2366
-
2367
- it "returns the max of the provided field" do
2368
- expect(max).to eq(1000)
2369
- end
2370
- end
2371
-
2372
- context "when provided a block" do
2373
-
2374
- let(:max) do
2375
- criteria.max do |a, b|
2376
- a.likes <=> b.likes
2377
- end
2378
- end
2379
-
2380
- it "returns the document with the max value for the field" do
2381
- expect(max).to eq(depeche)
2382
- end
2383
- end
2384
- end
2385
- end
2386
-
2387
- describe "#max_distance" do
2388
-
2389
- before do
2390
- Bar.create_indexes
2391
- end
2392
-
2393
- let!(:match) do
2394
- Bar.create(location: [ 52.30, 13.25 ])
2395
- end
2396
-
2397
- let!(:non_match) do
2398
- Bar.create(location: [ 19.26, 99.70 ])
2399
- end
2400
-
2401
- let(:criteria) do
2402
- Bar.near(location: [ 52, 13 ]).max_distance(location: 5)
2403
- end
2404
-
2405
- it "returns the matching documents" do
2406
- expect(criteria).to eq([ match ])
2407
- end
2408
- end
2409
-
2410
- describe "#merge" do
2411
-
2412
- let(:band) do
2413
- Band.new
2414
- end
2415
-
2416
- let(:criteria) do
2417
- Band.scoped.where(name: "Depeche Mode").asc(:name)
2418
- end
2419
-
2420
- context "when merging with another criteria" do
2421
-
2422
- let(:mergeable) do
2423
- Band.includes(:records).tap do |crit|
2424
- crit.documents = [ band ]
2425
- end
2426
- end
2427
-
2428
- let(:association) do
2429
- Band.relations["records"]
2430
- end
2431
-
2432
- let(:merged) do
2433
- criteria.merge(mergeable)
2434
- end
2435
-
2436
- it "merges the selector" do
2437
- expect(merged.selector).to eq({ "name" => "Depeche Mode" })
2438
- end
2439
-
2440
- it "merges the options" do
2441
- expect(merged.options).to eq({ sort: { "name" => 1 }})
2442
- end
2443
-
2444
- it "merges the documents" do
2445
- expect(merged.documents).to eq([ band ])
2446
- end
2447
-
2448
- it "merges the scoping options" do
2449
- expect(merged.scoping_options).to eq([ nil, nil ])
2450
- end
2451
-
2452
- it "merges the inclusions" do
2453
- expect(merged.inclusions).to eq([ association ])
2454
- end
2455
-
2456
- it "returns a new criteria" do
2457
- expect(merged).to_not equal(criteria)
2458
- end
2459
- end
2460
-
2461
- context "when merging with a hash" do
1427
+ context "when merging with a hash" do
2462
1428
 
2463
1429
  let(:mergeable) do
2464
1430
  { klass: Band, includes: [ :records ] }
@@ -2548,11 +1514,11 @@ describe Mongoid::Criteria do
2548
1514
  context "when provided a single field" do
2549
1515
 
2550
1516
  let!(:depeche) do
2551
- Band.create(name: "Depeche Mode", likes: 1000)
1517
+ Band.create!(name: "Depeche Mode", likes: 1000)
2552
1518
  end
2553
1519
 
2554
1520
  let!(:tool) do
2555
- Band.create(name: "Tool", likes: 500)
1521
+ Band.create!(name: "Tool", likes: 500)
2556
1522
  end
2557
1523
 
2558
1524
  let(:criteria) do
@@ -2588,11 +1554,11 @@ describe Mongoid::Criteria do
2588
1554
  describe "#mod" do
2589
1555
 
2590
1556
  let!(:match) do
2591
- Band.create(member_count: 5)
1557
+ Band.create!(member_count: 5)
2592
1558
  end
2593
1559
 
2594
1560
  let!(:non_match) do
2595
- Band.create(member_count: 2)
1561
+ Band.create!(member_count: 2)
2596
1562
  end
2597
1563
 
2598
1564
  let(:criteria) do
@@ -2607,11 +1573,11 @@ describe Mongoid::Criteria do
2607
1573
  describe "#ne" do
2608
1574
 
2609
1575
  let!(:match) do
2610
- Band.create(name: "Depeche Mode")
1576
+ Band.create!(name: "Depeche Mode")
2611
1577
  end
2612
1578
 
2613
1579
  let!(:non_match) do
2614
- Band.create(name: "Tool")
1580
+ Band.create!(name: "Tool")
2615
1581
  end
2616
1582
 
2617
1583
  let(:criteria) do
@@ -2630,286 +1596,72 @@ describe Mongoid::Criteria do
2630
1596
  end
2631
1597
 
2632
1598
  let!(:match) do
2633
- Bar.create(location: [ 52.30, 13.25 ])
1599
+ Bar.create!(location: [ 52.30, 13.25 ])
2634
1600
  end
2635
1601
 
2636
1602
  let(:criteria) do
2637
1603
  Bar.near(location: [ 52, 13 ])
2638
- end
2639
-
2640
- it "returns the matching documents" do
2641
- expect(criteria).to eq([ match ])
2642
- end
2643
- end
2644
-
2645
- describe "#near_sphere" do
2646
-
2647
- before do
2648
- Bar.create_indexes
2649
- end
2650
-
2651
- let!(:match) do
2652
- Bar.create(location: [ 52.30, 13.25 ])
2653
- end
2654
-
2655
- let(:criteria) do
2656
- Bar.near_sphere(location: [ 52, 13 ])
2657
- end
2658
-
2659
- it "returns the matching documents" do
2660
- expect(criteria).to eq([ match ])
2661
- end
2662
- end
2663
-
2664
- describe "#nin" do
2665
-
2666
- let!(:match) do
2667
- Band.create(name: "Depeche Mode")
2668
- end
2669
-
2670
- let!(:non_match) do
2671
- Band.create(name: "Tool")
2672
- end
2673
-
2674
- let(:criteria) do
2675
- Band.nin(name: [ "Tool" ])
2676
- end
2677
-
2678
- it "returns the matching documents" do
2679
- expect(criteria).to eq([ match ])
2680
- end
2681
- end
2682
-
2683
- describe "#nor" do
2684
-
2685
- let!(:match) do
2686
- Band.create(name: "Depeche Mode")
2687
- end
2688
-
2689
- let!(:non_match) do
2690
- Band.create(name: "Tool")
2691
- end
2692
-
2693
- let(:criteria) do
2694
- Band.nor({ name: "Tool" }, { name: "New Order" })
2695
- end
2696
-
2697
- it "returns the matching documents" do
2698
- expect(criteria).to eq([ match ])
2699
- end
2700
- end
2701
-
2702
- describe "#only" do
2703
-
2704
- let!(:band) do
2705
- Band.create(name: "Depeche Mode", likes: 3, views: 10)
2706
- end
2707
-
2708
- context "when not using inheritance" do
2709
-
2710
- context "when passing splat args" do
2711
-
2712
- let(:criteria) do
2713
- Band.only(:_id)
2714
- end
2715
-
2716
- it "limits the returned fields" do
2717
- expect {
2718
- criteria.first.name
2719
- }.to raise_error(ActiveModel::MissingAttributeError)
2720
- end
2721
-
2722
- it "does not add _type to the fields" do
2723
- expect(criteria.options[:fields]["_type"]).to be_nil
2724
- end
2725
- end
2726
-
2727
- context "when not including id" do
2728
-
2729
- let(:criteria) do
2730
- Band.only(:name)
2731
- end
2732
-
2733
- it "responds to id anyway" do
2734
- expect {
2735
- criteria.first.id
2736
- }.to_not raise_error
2737
- end
2738
- end
2739
-
2740
- context "when passing an array" do
2741
-
2742
- let(:criteria) do
2743
- Band.only([ :name, :likes ])
2744
- end
2745
-
2746
- it "includes the limited fields" do
2747
- expect(criteria.first.name).to_not be_nil
2748
- end
2749
-
2750
- it "excludes the non included fields" do
2751
- expect {
2752
- criteria.first.active
2753
- }.to raise_error(ActiveModel::MissingAttributeError)
2754
- end
2755
-
2756
- it "does not add _type to the fields" do
2757
- expect(criteria.options[:fields]["_type"]).to be_nil
2758
- end
2759
- end
2760
-
2761
- context "when instantiating a class of another type inside the iteration" do
2762
-
2763
- let(:criteria) do
2764
- Band.only(:name)
2765
- end
2766
-
2767
- it "only limits the fields on the correct model" do
2768
- criteria.each do |band|
2769
- expect(Person.new.age).to eq(100)
2770
- end
2771
- end
2772
- end
2773
-
2774
- context "when instantiating a document not in the result set" do
2775
-
2776
- let(:criteria) do
2777
- Band.only(:name)
2778
- end
2779
-
2780
- it "only limits the fields on the correct criteria" do
2781
- criteria.each do |band|
2782
- expect(Band.new.active).to be true
2783
- end
2784
- end
2785
- end
2786
-
2787
- context "when nesting a criteria within a criteria" do
2788
-
2789
- let(:criteria) do
2790
- Band.only(:name)
2791
- end
2792
-
2793
- it "only limits the fields on the correct criteria" do
2794
- criteria.each do |band|
2795
- Band.all.each do |b|
2796
- expect(b.active).to be true
2797
- end
2798
- end
2799
- end
2800
- end
2801
- end
2802
-
2803
- context "when using inheritance" do
2804
-
2805
- let(:criteria) do
2806
- Doctor.only(:_id)
2807
- end
2808
-
2809
- it "adds _type to the fields" do
2810
- expect(criteria.options[:fields]["_type"]).to eq(1)
2811
- end
2812
- end
2813
-
2814
- context "when limiting to embedded documents" do
2815
-
2816
- context "when the embedded documents are aliased" do
2817
-
2818
- let(:criteria) do
2819
- Person.only(:phones)
2820
- end
2821
-
2822
- it "properly uses the database field name" do
2823
- expect(criteria.options).to eq(fields: { "_id" => 1, "mobile_phones" => 1 })
2824
- end
2825
- end
2826
- end
2827
-
2828
- context 'when the field is localized' do
2829
-
2830
- before do
2831
- I18n.locale = :en
2832
- d = Dictionary.create(description: 'english-text')
2833
- I18n.locale = :de
2834
- d.description = 'deutsch-text'
2835
- d.save
2836
- end
2837
-
2838
- after do
2839
- I18n.locale = :en
2840
- end
2841
-
2842
- context 'when entire field is included' do
1604
+ end
2843
1605
 
2844
- let(:dictionary) do
2845
- Dictionary.only(:description).first
1606
+ it "returns the matching documents" do
1607
+ expect(criteria).to eq([ match ])
1608
+ end
1609
+ end
2846
1610
 
2847
- end
1611
+ describe "#near_sphere" do
2848
1612
 
2849
- it 'loads all translations' do
2850
- expect(dictionary.description_translations.keys).to include('de', 'en')
2851
- end
1613
+ before do
1614
+ Bar.create_indexes
1615
+ end
2852
1616
 
2853
- it 'returns the field value for the current locale' do
2854
- I18n.locale = :en
2855
- expect(dictionary.description).to eq('english-text')
2856
- I18n.locale = :de
2857
- expect(dictionary.description).to eq('deutsch-text')
2858
- end
2859
- end
1617
+ let!(:match) do
1618
+ Bar.create!(location: [ 52.30, 13.25 ])
1619
+ end
2860
1620
 
2861
- context 'when a specific locale is included' do
1621
+ let(:criteria) do
1622
+ Bar.near_sphere(location: [ 52, 13 ])
1623
+ end
2862
1624
 
2863
- let(:dictionary) do
2864
- Dictionary.only(:'description.de').first
2865
- end
1625
+ it "returns the matching documents" do
1626
+ expect(criteria).to eq([ match ])
1627
+ end
1628
+ end
2866
1629
 
2867
- it 'loads translations only for the included locale' do
2868
- expect(dictionary.description_translations.keys).to include('de')
2869
- expect(dictionary.description_translations.keys).to_not include('en')
2870
- end
1630
+ describe "#nin" do
2871
1631
 
2872
- it 'returns the field value for the included locale' do
2873
- I18n.locale = :en
2874
- expect(dictionary.description).to be_nil
2875
- I18n.locale = :de
2876
- expect(dictionary.description).to eq('deutsch-text')
2877
- end
2878
- end
1632
+ let!(:match) do
1633
+ Band.create!(name: "Depeche Mode")
1634
+ end
2879
1635
 
2880
- context 'when entire field is excluded' do
1636
+ let!(:non_match) do
1637
+ Band.create!(name: "Tool")
1638
+ end
2881
1639
 
2882
- let(:dictionary) do
2883
- Dictionary.without(:description).first
2884
- end
1640
+ let(:criteria) do
1641
+ Band.nin(name: [ "Tool" ])
1642
+ end
2885
1643
 
2886
- it 'does not load all translations' do
2887
- expect(dictionary.description_translations.keys).to_not include('de', 'en')
2888
- end
1644
+ it "returns the matching documents" do
1645
+ expect(criteria).to eq([ match ])
1646
+ end
1647
+ end
2889
1648
 
2890
- it 'raises an ActiveModel::MissingAttributeError when attempting to access the field' do
2891
- expect{dictionary.description}.to raise_error ActiveModel::MissingAttributeError
2892
- end
2893
- end
1649
+ describe "#nor" do
2894
1650
 
2895
- context 'when a specific locale is excluded' do
1651
+ let!(:match) do
1652
+ Band.create!(name: "Depeche Mode")
1653
+ end
2896
1654
 
2897
- let(:dictionary) do
2898
- Dictionary.without(:'description.de').first
2899
- end
1655
+ let!(:non_match) do
1656
+ Band.create!(name: "Tool")
1657
+ end
2900
1658
 
2901
- it 'does not load excluded translations' do
2902
- expect(dictionary.description_translations.keys).to_not include('de')
2903
- expect(dictionary.description_translations.keys).to include('en')
2904
- end
1659
+ let(:criteria) do
1660
+ Band.nor({ name: "Tool" }, { name: "New Order" })
1661
+ end
2905
1662
 
2906
- it 'returns nil for excluded translations' do
2907
- I18n.locale = :en
2908
- expect(dictionary.description).to eq('english-text')
2909
- I18n.locale = :de
2910
- expect(dictionary.description).to be_nil
2911
- end
2912
- end
1663
+ it "returns the matching documents" do
1664
+ expect(criteria).to eq([ match ])
2913
1665
  end
2914
1666
  end
2915
1667
 
@@ -2918,11 +1670,11 @@ describe Mongoid::Criteria do
2918
1670
  describe "\##{method}" do
2919
1671
 
2920
1672
  let!(:match) do
2921
- Band.create(name: "Depeche Mode")
1673
+ Band.create!(name: "Depeche Mode")
2922
1674
  end
2923
1675
 
2924
1676
  let!(:non_match) do
2925
- Band.create(name: "Tool")
1677
+ Band.create!(name: "Tool")
2926
1678
  end
2927
1679
 
2928
1680
  context "when sending a normal $or criterion" do
@@ -2952,25 +1704,29 @@ describe Mongoid::Criteria do
2952
1704
  describe "#pluck" do
2953
1705
 
2954
1706
  let!(:depeche) do
2955
- Band.create(name: "Depeche Mode", likes: 3)
1707
+ Band.create!(name: "Depeche Mode", likes: 3)
2956
1708
  end
2957
1709
 
2958
1710
  let!(:tool) do
2959
- Band.create(name: "Tool", likes: 3)
1711
+ Band.create!(name: "Tool", likes: 3)
2960
1712
  end
2961
1713
 
2962
1714
  let!(:photek) do
2963
- Band.create(name: "Photek", likes: 1)
1715
+ Band.create!(name: "Photek", likes: 1)
1716
+ end
1717
+
1718
+ let(:maniacs) do
1719
+ Band.create!(name: "10,000 Maniacs", likes: 1, sales: "1E2")
2964
1720
  end
2965
1721
 
2966
1722
  context "when the field is aliased" do
2967
1723
 
2968
1724
  let!(:expensive) do
2969
- Product.create(price: 100000)
1725
+ Product.create!(price: 100000)
2970
1726
  end
2971
1727
 
2972
1728
  let!(:cheap) do
2973
- Product.create(price: 1)
1729
+ Product.create!(price: 1)
2974
1730
  end
2975
1731
 
2976
1732
  context "when using alias_attribute" do
@@ -2979,8 +1735,10 @@ describe Mongoid::Criteria do
2979
1735
  Product.pluck(:price)
2980
1736
  end
2981
1737
 
2982
- it "uses the aliases" do
2983
- expect(plucked).to eq([ 100000, 1 ])
1738
+ with_config_values :legacy_pluck_distinct, true, false do
1739
+ it "uses the aliases" do
1740
+ expect(plucked).to eq([ 100000, 1 ])
1741
+ end
2984
1742
  end
2985
1743
  end
2986
1744
  end
@@ -2997,14 +1755,18 @@ describe Mongoid::Criteria do
2997
1755
  criteria.pluck(:name)
2998
1756
  end
2999
1757
 
3000
- it "returns the values" do
3001
- expect(plucked).to contain_exactly("Depeche Mode", "Tool", "Photek")
1758
+ with_config_values :legacy_pluck_distinct, true, false do
1759
+ it "returns the values" do
1760
+ expect(plucked).to contain_exactly("Depeche Mode", "Tool", "Photek")
1761
+ end
3002
1762
  end
3003
1763
 
3004
1764
  context "when subsequently executing the criteria without a pluck" do
3005
1765
 
3006
- it "does not limit the fields" do
3007
- expect(criteria.first.likes).to eq(3)
1766
+ with_config_values :legacy_pluck_distinct, true, false do
1767
+ it "does not limit the fields" do
1768
+ expect(criteria.first.likes).to eq(3)
1769
+ end
3008
1770
  end
3009
1771
  end
3010
1772
 
@@ -3015,51 +1777,83 @@ describe Mongoid::Criteria do
3015
1777
  end
3016
1778
 
3017
1779
  context 'when a top-level field and a subdocument field are plucked' do
3018
-
3019
1780
  before do
3020
- Band.create(name: 'FKA Twigs')
3021
- Band.create(name: 'FKA Twigs', records: [ Record.new(name: 'LP1') ])
1781
+ Band.create!(name: 'FKA Twigs')
1782
+ Band.create!(name: 'FKA Twigs', records: [ Record.new(name: 'LP1') ])
3022
1783
  end
3023
1784
 
3024
1785
  let(:embedded_pluck) do
3025
1786
  criteria.pluck(:name, 'records.name')
3026
1787
  end
3027
1788
 
3028
- let(:expected) do
3029
- [
3030
- ["FKA Twigs", nil],
3031
- ['FKA Twigs', [{ "name" => "LP1" }]]
3032
- ]
1789
+ context "when legacy_pluck_distinct is set" do
1790
+ config_override :legacy_pluck_distinct, true
1791
+ let(:expected) do
1792
+ [
1793
+ ["FKA Twigs", nil],
1794
+ ['FKA Twigs', [{ "name" => "LP1" }]]
1795
+ ]
1796
+ end
1797
+
1798
+ it 'returns the list of top-level field and subdocument values' do
1799
+ expect(embedded_pluck).to eq(expected)
1800
+ end
3033
1801
  end
3034
1802
 
3035
- it 'returns the list of top-level field and subdocument values' do
3036
- expect(embedded_pluck). to eq(expected)
1803
+ context "when legacy_pluck_distinct is not set" do
1804
+ config_override :legacy_pluck_distinct, false
1805
+ let(:expected) do
1806
+ [
1807
+ ["FKA Twigs", nil],
1808
+ ['FKA Twigs', ["LP1"]]
1809
+ ]
1810
+ end
1811
+
1812
+ it 'returns the list of top-level field and subdocument values' do
1813
+ expect(embedded_pluck).to eq(expected)
1814
+ end
3037
1815
  end
3038
1816
  end
3039
1817
 
3040
1818
  context 'when only a subdocument field is plucked' do
3041
1819
 
3042
1820
  before do
3043
- Band.create(name: 'FKA Twigs')
3044
- Band.create(name: 'FKA Twigs', records: [ Record.new(name: 'LP1') ])
1821
+ Band.create!(name: 'FKA Twigs')
1822
+ Band.create!(name: 'FKA Twigs', records: [ Record.new(name: 'LP1') ])
3045
1823
  end
3046
1824
 
3047
1825
  let(:embedded_pluck) do
3048
1826
  criteria.pluck('records.name')
3049
1827
  end
3050
1828
 
3051
- let(:expected) do
3052
- [
3053
- nil,
3054
- [{ "name" => "LP1" }]
3055
- ]
1829
+ context "when legacy_pluck_distinct is set" do
1830
+ config_override :legacy_pluck_distinct, true
1831
+ let(:expected) do
1832
+ [
1833
+ nil,
1834
+ [{ "name" => "LP1" }]
1835
+ ]
1836
+ end
1837
+
1838
+ it 'returns the list of subdocument values' do
1839
+ expect(embedded_pluck).to eq(expected)
1840
+ end
3056
1841
  end
3057
1842
 
3058
- it 'returns the list of subdocument values' do
3059
- expect(embedded_pluck). to eq(expected)
1843
+ context "when legacy_pluck_distinct is not set" do
1844
+ config_override :legacy_pluck_distinct, false
1845
+ let(:expected) do
1846
+ [
1847
+ nil,
1848
+ ["LP1"]
1849
+ ]
1850
+ end
1851
+
1852
+ it 'returns the list of subdocument values' do
1853
+ expect(embedded_pluck).to eq(expected)
1854
+ end
3060
1855
  end
3061
1856
  end
3062
-
3063
1857
  end
3064
1858
  end
3065
1859
 
@@ -3069,8 +1863,10 @@ describe Mongoid::Criteria do
3069
1863
  Band.where(:name.exists => true).pluck(:name, :likes)
3070
1864
  end
3071
1865
 
3072
- it "returns the values" do
3073
- expect(plucked).to contain_exactly(["Depeche Mode", 3], ["Tool", 3], ["Photek", 1])
1866
+ with_config_values :legacy_pluck_distinct, true, false do
1867
+ it "returns the values" do
1868
+ expect(plucked).to contain_exactly(["Depeche Mode", 3], ["Tool", 3], ["Photek", 1])
1869
+ end
3074
1870
  end
3075
1871
  end
3076
1872
 
@@ -3080,8 +1876,10 @@ describe Mongoid::Criteria do
3080
1876
  Band.where(:name.exists => true).pluck(:likes)
3081
1877
  end
3082
1878
 
3083
- it "returns the duplicates" do
3084
- expect(plucked).to contain_exactly(3, 3, 1)
1879
+ with_config_values :legacy_pluck_distinct, true, false do
1880
+ it "returns the duplicates" do
1881
+ expect(plucked).to contain_exactly(3, 3, 1)
1882
+ end
3085
1883
  end
3086
1884
  end
3087
1885
  end
@@ -3092,8 +1890,10 @@ describe Mongoid::Criteria do
3092
1890
  Band.where(name: "New Order").pluck(:_id)
3093
1891
  end
3094
1892
 
3095
- it "returns an empty array" do
3096
- expect(plucked).to be_empty
1893
+ with_config_values :legacy_pluck_distinct, true, false do
1894
+ it "returns an empty array" do
1895
+ expect(plucked).to be_empty
1896
+ end
3097
1897
  end
3098
1898
  end
3099
1899
 
@@ -3103,8 +1903,10 @@ describe Mongoid::Criteria do
3103
1903
  Band.all.pluck(:id)
3104
1904
  end
3105
1905
 
3106
- it "returns the field values" do
3107
- expect(plucked).to eq([ depeche.id, tool.id, photek.id ])
1906
+ with_config_values :legacy_pluck_distinct, true, false do
1907
+ it "returns the field values" do
1908
+ expect(plucked).to eq([ depeche.id, tool.id, photek.id ])
1909
+ end
3108
1910
  end
3109
1911
  end
3110
1912
 
@@ -3114,8 +1916,10 @@ describe Mongoid::Criteria do
3114
1916
  Band.all.pluck(:id, :fooz)
3115
1917
  end
3116
1918
 
3117
- it "returns nil for the field that doesnt exist" do
3118
- expect(plucked).to eq([[depeche.id, nil], [tool.id, nil], [photek.id, nil] ])
1919
+ with_config_values :legacy_pluck_distinct, true, false do
1920
+ it "returns nil for the field that doesnt exist" do
1921
+ expect(plucked).to eq([[depeche.id, nil], [tool.id, nil], [photek.id, nil] ])
1922
+ end
3119
1923
  end
3120
1924
  end
3121
1925
 
@@ -3127,8 +1931,10 @@ describe Mongoid::Criteria do
3127
1931
  Band.all.pluck(:foo)
3128
1932
  end
3129
1933
 
3130
- it "returns a array with nil values" do
3131
- expect(plucked).to eq([nil, nil, nil])
1934
+ with_config_values :legacy_pluck_distinct, true, false do
1935
+ it "returns an array with nil values" do
1936
+ expect(plucked).to eq([nil, nil, nil])
1937
+ end
3132
1938
  end
3133
1939
  end
3134
1940
 
@@ -3138,46 +1944,389 @@ describe Mongoid::Criteria do
3138
1944
  Band.all.pluck(:foo, :bar)
3139
1945
  end
3140
1946
 
3141
- it "returns a nil arrays" do
3142
- expect(plucked).to eq([[nil, nil], [nil, nil], [nil, nil]])
1947
+ with_config_values :legacy_pluck_distinct, true, false do
1948
+ it "returns an array of arrays with nil values" do
1949
+ expect(plucked).to eq([[nil, nil], [nil, nil], [nil, nil]])
1950
+ end
3143
1951
  end
3144
1952
  end
3145
1953
  end
3146
1954
 
3147
1955
  context 'when plucking a localized field' do
1956
+ with_default_i18n_configs
3148
1957
 
3149
1958
  before do
3150
1959
  I18n.locale = :en
3151
- d = Dictionary.create(description: 'english-text')
1960
+ d = Dictionary.create!(description: 'english-text')
3152
1961
  I18n.locale = :de
3153
1962
  d.description = 'deutsch-text'
3154
- d.save
1963
+ d.save!
3155
1964
  end
3156
1965
 
3157
- after do
3158
- I18n.locale = :en
1966
+ context 'when plucking the entire field' do
1967
+ let(:plucked) do
1968
+ Dictionary.all.pluck(:description)
1969
+ end
1970
+
1971
+ let(:plucked_translations) do
1972
+ Dictionary.all.pluck(:description_translations)
1973
+ end
1974
+
1975
+ let(:plucked_translations_both) do
1976
+ Dictionary.all.pluck(:description_translations, :description)
1977
+ end
1978
+
1979
+ context "when legacy_pluck_distinct is set" do
1980
+ config_override :legacy_pluck_distinct, true
1981
+
1982
+ it 'returns the non-demongoized translations' do
1983
+ expect(plucked.first).to eq({"de"=>"deutsch-text", "en"=>"english-text"})
1984
+ end
1985
+
1986
+ it 'returns nil' do
1987
+ expect(plucked_translations.first).to eq(nil)
1988
+ end
1989
+
1990
+ it 'returns nil for _translations' do
1991
+ expect(plucked_translations_both.first).to eq([nil, {"de"=>"deutsch-text", "en"=>"english-text"}])
1992
+ end
1993
+ end
1994
+
1995
+ context "when legacy_pluck_distinct is not set" do
1996
+ config_override :legacy_pluck_distinct, false
1997
+
1998
+ it 'returns the demongoized translations' do
1999
+ expect(plucked.first).to eq('deutsch-text')
2000
+ end
2001
+
2002
+ it 'returns the full translations hash to _translations' do
2003
+ expect(plucked_translations.first).to eq({"de"=>"deutsch-text", "en"=>"english-text"})
2004
+ end
2005
+
2006
+ it 'returns both' do
2007
+ expect(plucked_translations_both.first).to eq([{"de"=>"deutsch-text", "en"=>"english-text"}, "deutsch-text"])
2008
+ end
2009
+ end
3159
2010
  end
3160
2011
 
3161
- context 'when plucking the entire field' do
2012
+ context 'when plucking a specific locale' do
3162
2013
 
3163
2014
  let(:plucked) do
3164
- Dictionary.all.pluck(:description)
2015
+ Dictionary.all.pluck(:'description.de')
2016
+ end
2017
+
2018
+ context "when legacy_pluck_distinct is set" do
2019
+ config_override :legacy_pluck_distinct, true
2020
+
2021
+ it 'returns the specific translations' do
2022
+ expect(plucked.first).to eq({'de' => 'deutsch-text'})
2023
+ end
2024
+ end
2025
+
2026
+ context "when legacy_pluck_distinct is not set" do
2027
+ config_override :legacy_pluck_distinct, false
2028
+
2029
+ it 'returns the specific translations' do
2030
+ expect(plucked.first).to eq('deutsch-text')
2031
+ end
2032
+ end
2033
+ end
2034
+
2035
+ context 'when plucking a specific locale from _translations field' do
2036
+
2037
+ let(:plucked) do
2038
+ Dictionary.all.pluck(:'description_translations.de')
2039
+ end
2040
+
2041
+ context "when legacy_pluck_distinct is set" do
2042
+ config_override :legacy_pluck_distinct, true
2043
+
2044
+ it 'returns the specific translations' do
2045
+ expect(plucked.first).to eq(nil)
2046
+ end
2047
+ end
2048
+
2049
+ context "when legacy_pluck_distinct is not set" do
2050
+ config_override :legacy_pluck_distinct, false
2051
+
2052
+ it 'returns the specific translations' do
2053
+ expect(plucked.first).to eq('deutsch-text')
2054
+ end
2055
+ end
2056
+ end
2057
+
2058
+ context 'when fallbacks are enabled with a locale list' do
2059
+ require_fallbacks
2060
+
2061
+ before do
2062
+ I18n.fallbacks[:he] = [ :en ]
2063
+ end
2064
+
2065
+ let(:plucked) do
2066
+ Dictionary.all.pluck(:description).first
2067
+ end
2068
+
2069
+ context "when legacy_pluck_distinct is set" do
2070
+ config_override :legacy_pluck_distinct, true
2071
+
2072
+ it "does not correctly use the fallback" do
2073
+ plucked.should == {"de"=>"deutsch-text", "en"=>"english-text"}
2074
+ end
2075
+ end
2076
+
2077
+ context "when legacy_pluck_distinct is not set" do
2078
+ config_override :legacy_pluck_distinct, false
2079
+
2080
+ it "correctly uses the fallback" do
2081
+ I18n.locale = :en
2082
+ d = Dictionary.create!(description: 'english-text')
2083
+ I18n.locale = :he
2084
+ plucked.should == "english-text"
2085
+ end
2086
+ end
2087
+ end
2088
+
2089
+ context "when the localized field is embedded" do
2090
+ with_default_i18n_configs
2091
+
2092
+ before do
2093
+ p = Passport.new
2094
+ I18n.locale = :en
2095
+ p.name = "Neil"
2096
+ I18n.locale = :he
2097
+ p.name = "Nissim"
2098
+
2099
+ Person.create!(passport: p, employer_id: 12345)
2100
+ end
2101
+
2102
+ let(:plucked) do
2103
+ Person.where(employer_id: 12345).pluck("pass.name").first
2104
+ end
2105
+
2106
+ let(:plucked_translations) do
2107
+ Person.where(employer_id: 12345).pluck("pass.name_translations").first
2108
+ end
2109
+
2110
+ let(:plucked_translations_field) do
2111
+ Person.where(employer_id: 12345).pluck("pass.name_translations.en").first
2112
+ end
2113
+
2114
+ context "when legacy_pluck_distinct is set" do
2115
+ config_override :legacy_pluck_distinct, true
2116
+
2117
+ it "returns the full hash embedded" do
2118
+ expect(plucked).to eq({ "name" => { "en" => "Neil", "he" => "Nissim" } })
2119
+ end
2120
+
2121
+ it "returns the empty hash" do
2122
+ expect(plucked_translations).to eq({})
2123
+ end
2124
+
2125
+ it "returns the empty hash" do
2126
+ expect(plucked_translations_field).to eq({})
2127
+ end
2128
+ end
2129
+
2130
+ context "when legacy_pluck_distinct is not set" do
2131
+ config_override :legacy_pluck_distinct, false
2132
+
2133
+ it "returns the translation for the current locale" do
2134
+ expect(plucked).to eq("Nissim")
2135
+ end
2136
+
2137
+ it "returns the full _translation hash" do
2138
+ expect(plucked_translations).to eq({ "en" => "Neil", "he" => "Nissim" })
2139
+ end
2140
+
2141
+ it "returns the translation for the requested locale" do
2142
+ expect(plucked_translations_field).to eq("Neil")
2143
+ end
2144
+ end
2145
+ end
2146
+ end
2147
+
2148
+ context 'when plucking a field to be demongoized' do
2149
+
2150
+ let(:plucked) do
2151
+ Band.where(name: maniacs.name).pluck(:sales)
2152
+ end
2153
+
2154
+ context "when legacy_pluck_distinct is set" do
2155
+ config_override :legacy_pluck_distinct, true
2156
+
2157
+ context 'when value is stored as string' do
2158
+ config_override :map_big_decimal_to_decimal128, false
2159
+
2160
+ it "does not demongoize the field" do
2161
+ expect(plucked.first).to be_a(String)
2162
+ expect(plucked.first).to eq("1E2")
2163
+ end
2164
+ end
2165
+
2166
+ context 'when value is stored as decimal128' do
2167
+ config_override :map_big_decimal_to_decimal128, true
2168
+ max_bson_version '4.99.99'
2169
+
2170
+ it "does not demongoize the field" do
2171
+ expect(plucked.first).to be_a(BSON::Decimal128)
2172
+ expect(plucked.first).to eq(BSON::Decimal128.new("1E2"))
2173
+ end
2174
+ end
2175
+ end
2176
+
2177
+ context "when legacy_pluck_distinct is not set" do
2178
+ config_override :legacy_pluck_distinct, false
2179
+
2180
+ context 'when value is stored as string' do
2181
+ config_override :map_big_decimal_to_decimal128, false
2182
+
2183
+ it "demongoizes the field" do
2184
+ expect(plucked.first).to be_a(BigDecimal)
2185
+ expect(plucked.first).to eq(BigDecimal("1E2"))
2186
+ end
2187
+ end
2188
+
2189
+ context 'when value is stored as decimal128' do
2190
+ config_override :map_big_decimal_to_decimal128, true
2191
+
2192
+ it "demongoizes the field" do
2193
+ expect(plucked.first).to be_a(BigDecimal)
2194
+ expect(plucked.first).to eq(BigDecimal("1E2"))
2195
+ end
2196
+ end
2197
+ end
2198
+ end
2199
+
2200
+ context "when plucking an embedded field" do
2201
+ let(:label) { Label.new(sales: "1E2") }
2202
+ let!(:band) { Band.create!(label: label) }
2203
+
2204
+ let(:plucked) { Band.where(_id: band.id).pluck("label.sales") }
2205
+
2206
+ context "when legacy_pluck_distinct is set" do
2207
+ config_override :legacy_pluck_distinct, true
2208
+ config_override :map_big_decimal_to_decimal128, true
2209
+ max_bson_version '4.99.99'
2210
+
2211
+ it "returns a hash with a non-demongoized field" do
2212
+ expect(plucked.first).to eq({ 'sales' => BSON::Decimal128.new('1E+2') })
2213
+ end
2214
+ end
2215
+
2216
+ context "when legacy_pluck_distinct is not set" do
2217
+ config_override :legacy_pluck_distinct, false
2218
+
2219
+ it "demongoizes the field" do
2220
+ expect(plucked).to eq([ BigDecimal("1E2") ])
2221
+ end
2222
+ end
2223
+ end
2224
+
2225
+ context "when plucking an embeds_many field" do
2226
+ let(:label) { Label.new(sales: "1E2") }
2227
+ let!(:band) { Band.create!(labels: [label]) }
2228
+
2229
+ let(:plucked) { Band.where(_id: band.id).pluck("labels.sales") }
2230
+
2231
+ context "when legacy_pluck_distinct is set" do
2232
+ config_override :legacy_pluck_distinct, true
2233
+ config_override :map_big_decimal_to_decimal128, true
2234
+ max_bson_version '4.99.99'
2235
+
2236
+ it "returns a hash with a non-demongoized field" do
2237
+ expect(plucked.first).to eq([{ 'sales' => BSON::Decimal128.new('1E+2') }])
2238
+ end
2239
+ end
2240
+
2241
+ context "when legacy_pluck_distinct is not set" do
2242
+ config_override :legacy_pluck_distinct, false
2243
+
2244
+ it "demongoizes the field" do
2245
+ expect(plucked.first).to eq([ BigDecimal("1E2") ])
2246
+ end
2247
+ end
2248
+ end
2249
+
2250
+ context "when plucking a nonexistent embedded field" do
2251
+ let(:label) { Label.new(sales: "1E2") }
2252
+ let!(:band) { Band.create!(label: label) }
2253
+
2254
+ let(:plucked) { Band.where(_id: band.id).pluck("label.qwerty") }
2255
+
2256
+ context "when legacy_pluck_distinct is set" do
2257
+ config_override :legacy_pluck_distinct, true
2258
+
2259
+ it "returns an empty hash" do
2260
+ expect(plucked.first).to eq({})
3165
2261
  end
2262
+ end
2263
+
2264
+ context "when legacy_pluck_distinct is not set" do
2265
+ config_override :legacy_pluck_distinct, false
2266
+
2267
+ it "returns nil" do
2268
+ expect(plucked.first).to eq(nil)
2269
+ end
2270
+ end
2271
+ end
2272
+
2273
+ context "when tallying deeply nested arrays/embedded associations" do
2274
+
2275
+ before do
2276
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
2277
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 2 } } ]))) ])
2278
+ Person.create!(addresses: [ Address.new(code: Code.new(deepest: Deepest.new(array: [ { y: { z: 1 } }, { y: { z: 3 } } ]))) ])
2279
+ end
2280
+
2281
+ let(:plucked) do
2282
+ Person.pluck("addresses.code.deepest.array.y.z")
2283
+ end
2284
+
2285
+ it "returns the correct hash" do
2286
+ expect(plucked).to eq([
2287
+ [ [ 1, 2 ] ], [ [ 1, 2 ] ], [ [ 1, 3 ] ]
2288
+ ])
2289
+ end
2290
+ end
2291
+ end
2292
+
2293
+ describe "#pick" do
2294
+
2295
+ let!(:depeche) do
2296
+ Band.create!(name: "Depeche Mode", likes: 3)
2297
+ end
2298
+
2299
+ let!(:tool) do
2300
+ Band.create!(name: "Tool", likes: 3)
2301
+ end
2302
+
2303
+ context "when picking a field" do
2304
+
2305
+ let(:criteria) do
2306
+ Band.all
2307
+ end
2308
+
2309
+ let(:picked) do
2310
+ criteria.pick(:name)
2311
+ end
3166
2312
 
3167
- it 'returns all translations' do
3168
- expect(plucked.first).to eq({'en' => 'english-text', 'de' => 'deutsch-text'})
3169
- end
2313
+ it "returns one element" do
2314
+ expect(picked).to eq("Depeche Mode")
3170
2315
  end
2316
+ end
3171
2317
 
3172
- context 'when plucking a specific locale' do
2318
+ context "when picking multiple fields" do
3173
2319
 
3174
- let(:plucked) do
3175
- Dictionary.all.pluck(:'description.de')
3176
- end
2320
+ let(:criteria) do
2321
+ Band.all
2322
+ end
3177
2323
 
3178
- it 'returns the specific translations' do
3179
- expect(plucked.first).to eq({'de' => 'deutsch-text'})
3180
- end
2324
+ let(:picked) do
2325
+ criteria.pick(:name, :likes)
2326
+ end
2327
+
2328
+ it "returns an array" do
2329
+ expect(picked).to eq([ "Depeche Mode", 3 ])
3181
2330
  end
3182
2331
  end
3183
2332
  end
@@ -3263,11 +2412,11 @@ describe Mongoid::Criteria do
3263
2412
  describe "#sort" do
3264
2413
 
3265
2414
  let!(:depeche) do
3266
- Band.create(name: "Depeche Mode", likes: 1000)
2415
+ Band.create!(name: "Depeche Mode", likes: 1000)
3267
2416
  end
3268
2417
 
3269
2418
  let!(:tool) do
3270
- Band.create(name: "Tool", likes: 500)
2419
+ Band.create!(name: "Tool", likes: 500)
3271
2420
  end
3272
2421
 
3273
2422
  let(:sorted) do
@@ -3286,11 +2435,11 @@ describe Mongoid::Criteria do
3286
2435
  context "when provided a single field" do
3287
2436
 
3288
2437
  let!(:depeche) do
3289
- Band.create(name: "Depeche Mode", likes: 1000)
2438
+ Band.create!(name: "Depeche Mode", likes: 1000)
3290
2439
  end
3291
2440
 
3292
2441
  let!(:tool) do
3293
- Band.create(name: "Tool", likes: 500)
2442
+ Band.create!(name: "Tool", likes: 500)
3294
2443
  end
3295
2444
 
3296
2445
  let(:criteria) do
@@ -3324,7 +2473,7 @@ describe Mongoid::Criteria do
3324
2473
  describe "#to_ary" do
3325
2474
 
3326
2475
  let!(:band) do
3327
- Band.create(name: "Depeche Mode")
2476
+ Band.create!(name: "Depeche Mode")
3328
2477
  end
3329
2478
 
3330
2479
  let(:criteria) do
@@ -3340,11 +2489,11 @@ describe Mongoid::Criteria do
3340
2489
  max_server_version '4.0'
3341
2490
 
3342
2491
  let!(:band) do
3343
- Band.create(name: "Depeche Mode")
2492
+ Band.create!(name: "Depeche Mode")
3344
2493
  end
3345
2494
 
3346
2495
  let!(:band2) do
3347
- Band.create(name: "Tool")
2496
+ Band.create!(name: "Tool")
3348
2497
  end
3349
2498
 
3350
2499
  let(:criteria) do
@@ -3383,34 +2532,75 @@ describe Mongoid::Criteria do
3383
2532
  end
3384
2533
 
3385
2534
  describe "#type" do
2535
+ context "when using the default discriminator_key" do
2536
+ context "when the type is a string" do
3386
2537
 
3387
- context "when the type is a string" do
2538
+ let!(:browser) do
2539
+ Browser.create!
2540
+ end
3388
2541
 
3389
- let!(:browser) do
3390
- Browser.create
3391
- end
2542
+ let(:criteria) do
2543
+ Canvas.all.type("Browser")
2544
+ end
3392
2545
 
3393
- let(:criteria) do
3394
- Canvas.all.type("Browser")
2546
+ it "returns documents with the provided type" do
2547
+ expect(criteria).to eq([ browser ])
2548
+ end
3395
2549
  end
3396
2550
 
3397
- it "returns documents with the provided type" do
3398
- expect(criteria).to eq([ browser ])
2551
+ context "when the type is an Array of type" do
2552
+
2553
+ let!(:browser) do
2554
+ Firefox.create!
2555
+ end
2556
+
2557
+ let(:criteria) do
2558
+ Canvas.all.type([ "Browser", "Firefox" ])
2559
+ end
2560
+
2561
+ it "returns documents with the provided types" do
2562
+ expect(criteria).to eq([ browser ])
2563
+ end
3399
2564
  end
3400
2565
  end
3401
2566
 
3402
- context "when the type is an Array of type" do
2567
+ context "when using a custom discriminator_key" do
2568
+ before do
2569
+ Canvas.discriminator_key = "dkey"
2570
+ end
3403
2571
 
3404
- let!(:browser) do
3405
- Firefox.create
2572
+ after do
2573
+ Canvas.discriminator_key = nil
3406
2574
  end
3407
2575
 
3408
- let(:criteria) do
3409
- Canvas.all.type([ "Browser", "Firefox" ])
2576
+ context "when the type is a string" do
2577
+
2578
+ let!(:browser) do
2579
+ Browser.create!
2580
+ end
2581
+
2582
+ let(:criteria) do
2583
+ Canvas.all.type("Browser")
2584
+ end
2585
+
2586
+ it "returns documents with the provided type" do
2587
+ expect(criteria).to eq([ browser ])
2588
+ end
3410
2589
  end
3411
2590
 
3412
- it "returns documents with the provided types" do
3413
- expect(criteria).to eq([ browser ])
2591
+ context "when the type is an Array of type" do
2592
+
2593
+ let!(:browser) do
2594
+ Firefox.create!
2595
+ end
2596
+
2597
+ let(:criteria) do
2598
+ Canvas.all.type([ "Browser", "Firefox" ])
2599
+ end
2600
+
2601
+ it "returns documents with the provided types" do
2602
+ expect(criteria).to eq([ browser ])
2603
+ end
3414
2604
  end
3415
2605
  end
3416
2606
  end
@@ -3418,11 +2608,43 @@ describe Mongoid::Criteria do
3418
2608
  describe "#where" do
3419
2609
 
3420
2610
  let!(:match) do
3421
- Band.create(name: "Depeche Mode")
2611
+ Band.create!(name: "Depeche Mode")
3422
2612
  end
3423
2613
 
3424
2614
  let!(:non_match) do
3425
- Band.create(name: "Tool")
2615
+ Band.create!(name: "Tool")
2616
+ end
2617
+
2618
+ context 'when provided no arguments' do
2619
+ context 'on a model class' do
2620
+ it 'returns an empty criteria' do
2621
+ Band.where.selector.should == {}
2622
+ end
2623
+ end
2624
+
2625
+ context 'on an association' do
2626
+ it 'returns an empty criteria' do
2627
+ match.records.where.selector.should == {}
2628
+ end
2629
+ end
2630
+ end
2631
+
2632
+ context 'when provided multiple arguments' do
2633
+ context 'on a model class' do
2634
+ it 'raises ArgumentError' do
2635
+ lambda do
2636
+ Band.where({foo: 1}, {bar: 2})
2637
+ end.should raise_error(ArgumentError, /where requires zero or one arguments/)
2638
+ end
2639
+ end
2640
+
2641
+ context 'on an association' do
2642
+ it 'raises ArgumentError' do
2643
+ lambda do
2644
+ match.records.where({foo: 1}, {bar: 2})
2645
+ end.should raise_error(ArgumentError, /where requires zero or one arguments/)
2646
+ end
2647
+ end
3426
2648
  end
3427
2649
 
3428
2650
  context "when provided a string" do
@@ -3482,31 +2704,121 @@ describe Mongoid::Criteria do
3482
2704
 
3483
2705
  context "when querying on a big decimal" do
3484
2706
 
3485
- let(:sales) do
3486
- BigDecimal('0.1')
2707
+ context 'when map_big_decimal_to_decimal128 is false' do
2708
+ config_override :map_big_decimal_to_decimal128, false
2709
+
2710
+ let(:sales) do
2711
+ BigDecimal('0.1')
2712
+ end
2713
+
2714
+ let!(:band) do
2715
+ Band.create!(name: "Boards of Canada", sales: sales)
2716
+ end
2717
+
2718
+ let(:from_db) do
2719
+ Band.where(sales: sales).first
2720
+ end
2721
+
2722
+ it "finds the document by the big decimal value" do
2723
+ expect(from_db).to eq(band)
2724
+ end
3487
2725
  end
3488
2726
 
3489
- let!(:band) do
3490
- Band.create(name: "Boards of Canada", sales: sales)
2727
+ context 'when map_big_decimal_to_decimal128 is true' do
2728
+ config_override :map_big_decimal_to_decimal128, true
2729
+
2730
+ let(:sales) do
2731
+ BigDecimal('0.1')
2732
+ end
2733
+
2734
+ let!(:band) do
2735
+ Band.create!(name: "Boards of Canada", sales: sales)
2736
+ end
2737
+
2738
+ let(:from_db) do
2739
+ Band.where(sales: sales).first
2740
+ end
2741
+
2742
+ it "finds the document by the big decimal value" do
2743
+ expect(from_db).to eq(band)
2744
+ end
3491
2745
  end
3492
2746
 
3493
- let(:from_db) do
3494
- Band.where(sales: sales).first
2747
+ context 'when map_big_decimal_to_decimal128 was false and is now true' do
2748
+ config_override :map_big_decimal_to_decimal128, false
2749
+
2750
+ let(:sales) do
2751
+ BigDecimal('0.1')
2752
+ end
2753
+
2754
+ let!(:band) do
2755
+ Mongoid.map_big_decimal_to_decimal128 = false
2756
+ Band.create!(name: "Boards of Canada", sales: sales)
2757
+ end
2758
+
2759
+ let(:from_db) do
2760
+ Mongoid.map_big_decimal_to_decimal128 = true
2761
+ Band.where(sales: sales.to_s).first
2762
+ end
2763
+
2764
+ it "finds the document by the big decimal value" do
2765
+ expect(from_db).to eq(band)
2766
+ end
3495
2767
  end
2768
+ end
3496
2769
 
3497
- it "finds the document by the big decimal value" do
3498
- expect(from_db).to eq(band)
2770
+ context "when querying on a big decimal from a dynamic field" do
2771
+
2772
+ context 'when map_big_decimal_to_decimal128 is false' do
2773
+ config_override :map_big_decimal_to_decimal128, false
2774
+
2775
+ let(:fans) do
2776
+ BigDecimal('139432.0002')
2777
+ end
2778
+
2779
+ let!(:band) do
2780
+ Band.create!(name: "Boards of Canada", fans: fans)
2781
+ end
2782
+
2783
+ let(:from_db) do
2784
+ Band.where(fans: fans.to_s).first
2785
+ end
2786
+
2787
+ it "finds the document by the big decimal value" do
2788
+ expect(from_db).to eq(band)
2789
+ end
2790
+ end
2791
+
2792
+ context 'when map_big_decimal_to_decimal128 is true' do
2793
+ config_override :map_big_decimal_to_decimal128, true
2794
+
2795
+ let(:fans) do
2796
+ BigDecimal('139432.0002')
2797
+ end
2798
+
2799
+ let!(:band) do
2800
+ Band.create!(name: "Boards of Canada", fans: fans)
2801
+ end
2802
+
2803
+ let(:from_db) do
2804
+ Band.where(fans: fans).first
2805
+ end
2806
+
2807
+ it "only finds the document by the string value" do
2808
+ expect(from_db).to eq(band)
2809
+ end
3499
2810
  end
3500
2811
  end
3501
2812
 
3502
- context "when querying on a BSON::Decimal128", if: decimal128_supported? do
2813
+ context "when querying on a BSON::Decimal128" do
2814
+ min_server_version '3.4'
3503
2815
 
3504
2816
  let(:decimal) do
3505
2817
  BSON::Decimal128.new("0.0005")
3506
2818
  end
3507
2819
 
3508
2820
  let!(:band) do
3509
- Band.create(name: "Boards of Canada", decimal: decimal)
2821
+ Band.create!(name: "Boards of Canada", decimal: decimal)
3510
2822
  end
3511
2823
 
3512
2824
  let(:from_db) do
@@ -3521,7 +2833,7 @@ describe Mongoid::Criteria do
3521
2833
  context 'when querying on a polymorphic relation' do
3522
2834
 
3523
2835
  let(:movie) do
3524
- Movie.create
2836
+ Movie.create!
3525
2837
  end
3526
2838
 
3527
2839
  let(:selector) do
@@ -3533,12 +2845,289 @@ describe Mongoid::Criteria do
3533
2845
  end
3534
2846
  end
3535
2847
  end
2848
+
2849
+ context 'when given multiple keys in separate calls' do
2850
+ let(:criteria) { Band.where(foo: 1).where(bar: 2) }
2851
+
2852
+ it 'combines criteria' do
2853
+ expect(criteria.selector).to eq('foo' => 1, 'bar' => 2)
2854
+ end
2855
+ end
2856
+
2857
+ context 'when given same key in separate calls' do
2858
+ let(:criteria) { Band.where(foo: 1).where(foo: 2) }
2859
+
2860
+ it 'combines criteria' do
2861
+ expect(criteria.selector).to eq('foo' => 1, '$and' => [{'foo' => 2}])
2862
+ end
2863
+ end
2864
+
2865
+ context 'when given same key in separate calls and there are other criteria' do
2866
+ let(:criteria) { Band.where(foo: 1, bar: 3).where(foo: 2) }
2867
+
2868
+ it 'combines criteria' do
2869
+ expect(criteria.selector).to eq(
2870
+ 'foo' => 1, '$and' => [{'foo' => 2}], 'bar' => 3)
2871
+ end
2872
+ end
2873
+
2874
+ context 'when given same key in separate calls and other criteria are added later' do
2875
+ let(:criteria) { Band.where(foo: 1).where(foo: 2).where(bar: 3) }
2876
+
2877
+ it 'combines criteria' do
2878
+ expect(criteria.selector).to eq(
2879
+ 'foo' => 1, '$and' => [{'foo' => 2}], 'bar' => 3)
2880
+ end
2881
+ end
2882
+
2883
+ context "when duplicating where conditions" do
2884
+ let(:criteria) { Sound.where(active: true).where(active: true) }
2885
+
2886
+ it 'does not duplicate criteria' do
2887
+ expect(criteria.selector).to eq('active' => true)
2888
+ end
2889
+ end
2890
+
2891
+ context "when duplicating where conditions with different values" do
2892
+ let(:criteria) { Sound.where(active: true).where(active: false).where(active: true).where(active: false) }
2893
+
2894
+ it 'does not duplicate criteria' do
2895
+ expect(criteria.selector).to eq(
2896
+ 'active' => true, '$and' => [{'active' => false}])
2897
+ end
2898
+ end
2899
+
2900
+ # Used to test MONGOID-5251 where the find command was adding unnecessary
2901
+ # and clauses. Since the find command creates the criteria and executes it,
2902
+ # it is difficult to analyze the criteria used. For this reason, I have
2903
+ # extracted the crux of the issue, adding an _id to the the criteria twice,
2904
+ # and used that for the test case.
2905
+ context "when searching by _id twice" do
2906
+ let(:_id) { BSON::ObjectId.new }
2907
+ let(:criteria) { Band.where(_id: _id) }
2908
+ let(:dup_criteria) { criteria.where(_id: _id)}
2909
+
2910
+ it "does not duplicate the criteria" do
2911
+ expect(dup_criteria.selector).to eq({ "_id" => _id })
2912
+ end
2913
+ end
2914
+
2915
+ context "when querying an embedded field" do
2916
+ let(:criteria) { Band.where("label.name": 12345) }
2917
+
2918
+ it "mongoizes the embedded field in the selector" do
2919
+ expect(criteria.selector).to eq("label.name" => "12345")
2920
+ end
2921
+ end
2922
+
2923
+ context "when querying with a range" do
2924
+
2925
+ context "when querying an embeds_many association" do
2926
+ let(:criteria) do
2927
+ Band.where("labels" => 10..15)
2928
+ end
2929
+
2930
+ it "correctly uses elemMatch without an inner key" do
2931
+ expect(criteria.selector).to eq(
2932
+ "labels" => {
2933
+ "$elemMatch" => { "$gte" => 10, "$lte" => 15 }
2934
+ }
2935
+ )
2936
+ end
2937
+ end
2938
+
2939
+ context "when querying an element in an embeds_many association" do
2940
+ let(:criteria) do
2941
+ Band.where("labels.age" => 10..15)
2942
+ end
2943
+
2944
+ it "correctly uses elemMatch" do
2945
+ expect(criteria.selector).to eq(
2946
+ "labels" => {
2947
+ "$elemMatch" => {
2948
+ "age" => { "$gte" => 10, "$lte" => 15 }
2949
+ }
2950
+ }
2951
+ )
2952
+ end
2953
+ end
2954
+
2955
+ context "when querying a field of type array" do
2956
+ let(:criteria) do
2957
+ Band.where("genres" => 10..15)
2958
+ end
2959
+
2960
+ it "correctly uses elemMatch without an inner key" do
2961
+ expect(criteria.selector).to eq(
2962
+ "genres" => {
2963
+ "$elemMatch" => { "$gte" => 10, "$lte" => 15 }
2964
+ }
2965
+ )
2966
+ end
2967
+ end
2968
+
2969
+ context "when querying an aliased field of type array" do
2970
+ let(:criteria) do
2971
+ Person.where("array" => 10..15)
2972
+ end
2973
+
2974
+ it "correctly uses the aliased field and elemMatch" do
2975
+ expect(criteria.selector).to eq(
2976
+ "a" => {
2977
+ "$elemMatch" => { "$gte" => 10, "$lte" => 15 }
2978
+ }
2979
+ )
2980
+ end
2981
+ end
2982
+
2983
+ context "when querying a field inside an array" do
2984
+ let(:criteria) do
2985
+ Band.where("genres.age" => 10..15)
2986
+ end
2987
+
2988
+ it "correctly uses elemMatch" do
2989
+ expect(criteria.selector).to eq(
2990
+ "genres" => {
2991
+ "$elemMatch" => {
2992
+ "age" => { "$gte" => 10, "$lte" => 15 }
2993
+ }
2994
+ }
2995
+ )
2996
+ end
2997
+ end
2998
+
2999
+ context "when there are no embeds_manys or Arrays" do
3000
+ let(:criteria) do
3001
+ Band.where("fans.info.age" => 10..15)
3002
+ end
3003
+
3004
+ it "does not use elemMatch" do
3005
+ expect(criteria.selector).to eq(
3006
+ "fans.info.age" => { "$gte" => 10, "$lte" => 15 }
3007
+ )
3008
+ end
3009
+ end
3010
+
3011
+ context "when querying a nested element in an embeds_many association" do
3012
+ let(:criteria) do
3013
+ Band.where("labels.age.number" => 10..15)
3014
+ end
3015
+
3016
+ it "correctly uses elemMatch" do
3017
+ expect(criteria.selector).to eq(
3018
+ "labels" => {
3019
+ "$elemMatch" => {
3020
+ "age.number" => { "$gte" => 10, "$lte" => 15 }
3021
+ }
3022
+ }
3023
+ )
3024
+ end
3025
+ end
3026
+
3027
+ context "when querying a nested element in an Array" do
3028
+ let(:criteria) do
3029
+ Band.where("genres.name.length" => 10..15)
3030
+ end
3031
+
3032
+ it "correctly uses elemMatch" do
3033
+ expect(criteria.selector).to eq(
3034
+ "genres" => {
3035
+ "$elemMatch" => {
3036
+ "name.length" => { "$gte" => 10, "$lte" => 15 }
3037
+ }
3038
+ }
3039
+ )
3040
+ end
3041
+ end
3042
+
3043
+ context "when querying a nested element in a nested embeds_many association" do
3044
+ context "when the outer association is an embeds_many" do
3045
+ let(:criteria) do
3046
+ Band.where("records.tracks.name.length" => 10..15)
3047
+ end
3048
+
3049
+ it "correctly uses elemMatch" do
3050
+ expect(criteria.selector).to eq(
3051
+ "records.tracks" => {
3052
+ "$elemMatch" => {
3053
+ "name.length" => { "$gte" => 10, "$lte" => 15 }
3054
+ }
3055
+ }
3056
+ )
3057
+ end
3058
+ end
3059
+
3060
+ context "when the outer association is an embeds_one" do
3061
+ let(:criteria) do
3062
+ Person.where("name.translations.language.length" => 10..15)
3063
+ end
3064
+
3065
+ it "correctly uses elemMatch" do
3066
+ expect(criteria.selector).to eq(
3067
+ "name.translations" => {
3068
+ "$elemMatch" => {
3069
+ "language.length" => { "$gte" => 10, "$lte" => 15 }
3070
+ }
3071
+ }
3072
+ )
3073
+ end
3074
+ end
3075
+ end
3076
+
3077
+ context "when querying a deeply nested array" do
3078
+ let(:criteria) do
3079
+ Person.where("addresses.code.deepest.array.element.item" => 10..15)
3080
+ end
3081
+
3082
+ it "correctly uses elemMatch" do
3083
+ expect(criteria.selector).to eq(
3084
+ "addresses.code.deepest.array" => {
3085
+ "$elemMatch" => {
3086
+ "element.item" => { "$gte" => 10, "$lte" => 15 }
3087
+ }
3088
+ }
3089
+ )
3090
+ end
3091
+ end
3092
+
3093
+ context "when there are multiple conditions" do
3094
+ let(:criteria) do
3095
+ Band.where("$or" => [{"labels.age" => 10..15}, {labels: 8}])
3096
+ end
3097
+
3098
+ it "correctly combines the conditions" do
3099
+ expect(criteria.selector).to eq("$or" => [
3100
+ { "labels" => {
3101
+ "$elemMatch" => {
3102
+ "age" => { "$gte" => 10, "$lte" => 15 }
3103
+ } } },
3104
+ { "labels" => 8 }
3105
+ ])
3106
+ end
3107
+ end
3108
+
3109
+ context "when the association is aliased" do
3110
+ let(:criteria) do
3111
+ Person.where("passport.passport_pages.num_stamps" => 10..18)
3112
+ end
3113
+
3114
+ it "correctly uses the aliased association" do
3115
+ expect(criteria.selector).to eq(
3116
+ "pass.passport_pages" => {
3117
+ "$elemMatch" => {
3118
+ "num_stamps" => { "$gte" => 10, "$lte" => 18 }
3119
+ }
3120
+ }
3121
+ )
3122
+ end
3123
+ end
3124
+ end
3536
3125
  end
3537
3126
 
3538
3127
  describe "#for_js" do
3539
3128
 
3540
3129
  let!(:match) do
3541
- Band.create(name: "Depeche Mode")
3130
+ Band.create!(name: "Depeche Mode")
3542
3131
  end
3543
3132
 
3544
3133
  context "when the code has no scope" do
@@ -3553,6 +3142,7 @@ describe Mongoid::Criteria do
3553
3142
  end
3554
3143
 
3555
3144
  context "when the code has scope" do
3145
+ max_server_version '4.2'
3556
3146
 
3557
3147
  let(:criteria) do
3558
3148
  Band.for_js("this.name == param", param: "Depeche Mode")
@@ -3574,10 +3164,14 @@ describe Mongoid::Criteria do
3574
3164
 
3575
3165
  before do
3576
3166
  expect(Person).to receive(:minor).and_call_original
3167
+ expect(Person).to receive(:older_than).and_call_original
3577
3168
  end
3578
3169
 
3579
3170
  it "calls the method on the class" do
3580
3171
  expect(criteria.minor).to be_empty
3172
+ expect do
3173
+ criteria.older_than(age: 25)
3174
+ end.not_to raise_error
3581
3175
  end
3582
3176
  end
3583
3177
 
@@ -3620,11 +3214,11 @@ describe Mongoid::Criteria do
3620
3214
  describe "#uniq" do
3621
3215
 
3622
3216
  let!(:band_one) do
3623
- Band.create(name: "New Order")
3217
+ Band.create!(name: "New Order")
3624
3218
  end
3625
3219
 
3626
3220
  let!(:band_two) do
3627
- Band.create(name: "New Order")
3221
+ Band.create!(name: "New Order")
3628
3222
  end
3629
3223
 
3630
3224
  let(:criteria) do
@@ -3664,7 +3258,7 @@ describe Mongoid::Criteria do
3664
3258
  end
3665
3259
  end
3666
3260
 
3667
- describe "#geo_spacial" do
3261
+ describe "#geo_spatial" do
3668
3262
 
3669
3263
  context "when checking within a polygon" do
3670
3264
 
@@ -3673,11 +3267,11 @@ describe Mongoid::Criteria do
3673
3267
  end
3674
3268
 
3675
3269
  let!(:match) do
3676
- Bar.create(location: [ 52.30, 13.25 ])
3270
+ Bar.create!(location: [ 52.30, 13.25 ])
3677
3271
  end
3678
3272
 
3679
3273
  let(:criteria) do
3680
- Bar.geo_spacial(
3274
+ Bar.geo_spatial(
3681
3275
  :location.within_polygon => [[[ 50, 10 ], [ 50, 20 ], [ 60, 20 ], [ 60, 10 ], [ 50, 10 ]]]
3682
3276
  )
3683
3277
  end
@@ -3691,11 +3285,11 @@ describe Mongoid::Criteria do
3691
3285
  describe "#with_size" do
3692
3286
 
3693
3287
  let!(:match) do
3694
- Band.create(genres: [ "electro", "dub" ])
3288
+ Band.create!(genres: [ "electro", "dub" ])
3695
3289
  end
3696
3290
 
3697
3291
  let!(:non_match) do
3698
- Band.create(genres: [ "house" ])
3292
+ Band.create!(genres: [ "house" ])
3699
3293
  end
3700
3294
 
3701
3295
  let(:criteria) do
@@ -3710,7 +3304,7 @@ describe Mongoid::Criteria do
3710
3304
  describe "#with_type" do
3711
3305
 
3712
3306
  let!(:match) do
3713
- Band.create(name: "Depeche Mode")
3307
+ Band.create!(name: "Depeche Mode")
3714
3308
  end
3715
3309
 
3716
3310
  let(:criteria) do
@@ -3722,73 +3316,76 @@ describe Mongoid::Criteria do
3722
3316
  end
3723
3317
  end
3724
3318
 
3725
- describe "#without" do
3319
+ describe "#type_selection" do
3320
+ context "when using the default discriminator_key" do
3321
+ context "when only one subclass exists" do
3726
3322
 
3727
- let!(:person) do
3728
- Person.create!(username: "davinci", age: 50, pets: false)
3729
- end
3323
+ let(:criteria) do
3324
+ described_class.new(Firefox)
3325
+ end
3730
3326
 
3731
- context "when omitting to embedded documents" do
3327
+ let(:selection) do
3328
+ criteria.send(:type_selection)
3329
+ end
3330
+
3331
+ it "does not use an $in query" do
3332
+ expect(selection).to eq({ _type: "Firefox" })
3333
+ end
3334
+ end
3732
3335
 
3733
- context "when the embedded documents are aliased" do
3336
+ context "when more than one subclass exists" do
3734
3337
 
3735
3338
  let(:criteria) do
3736
- Person.without(:phones)
3339
+ described_class.new(Browser)
3737
3340
  end
3738
3341
 
3739
- it "properly uses the database field name" do
3740
- expect(criteria.options).to eq(fields: { "mobile_phones" => 0 })
3342
+ let(:selection) do
3343
+ criteria.send(:type_selection)
3741
3344
  end
3742
- end
3743
- end
3744
3345
 
3745
- context "when excluding id" do
3746
-
3747
- let(:criteria) do
3748
- Person.without(:_id, :id, "_id", "id")
3346
+ it "does not use an $in query" do
3347
+ expect(selection).to eq({ _type: { "$in" => [ "Firefox", "Browser" ]}})
3348
+ end
3749
3349
  end
3350
+ end
3750
3351
 
3751
- it "does not raise error" do
3752
- expect {
3753
- criteria.first.id
3754
- }.to_not raise_error
3352
+ context "when using a custom discriminator_key" do
3353
+ before do
3354
+ Canvas.discriminator_key = "dkey"
3755
3355
  end
3756
3356
 
3757
- it "returns id anyway" do
3758
- expect(criteria.first.id).to_not be_nil
3357
+ after do
3358
+ Canvas.discriminator_key = nil
3759
3359
  end
3760
- end
3761
- end
3762
-
3763
- describe "#type_selection" do
3764
3360
 
3765
- context "when only one subclass exists" do
3361
+ context "when only one subclass exists" do
3766
3362
 
3767
- let(:criteria) do
3768
- described_class.new(Firefox)
3769
- end
3363
+ let(:criteria) do
3364
+ described_class.new(Firefox)
3365
+ end
3770
3366
 
3771
- let(:selection) do
3772
- criteria.send(:type_selection)
3773
- end
3367
+ let(:selection) do
3368
+ criteria.send(:type_selection)
3369
+ end
3774
3370
 
3775
- it "does not use an $in query" do
3776
- expect(selection).to eq({ _type: "Firefox" })
3371
+ it "does not use an $in query" do
3372
+ expect(selection).to eq({ dkey: "Firefox" })
3373
+ end
3777
3374
  end
3778
- end
3779
3375
 
3780
- context "when more than one subclass exists" do
3376
+ context "when more than one subclass exists" do
3781
3377
 
3782
- let(:criteria) do
3783
- described_class.new(Browser)
3784
- end
3378
+ let(:criteria) do
3379
+ described_class.new(Browser)
3380
+ end
3785
3381
 
3786
- let(:selection) do
3787
- criteria.send(:type_selection)
3788
- end
3382
+ let(:selection) do
3383
+ criteria.send(:type_selection)
3384
+ end
3789
3385
 
3790
- it "does not use an $in query" do
3791
- expect(selection).to eq({ _type: { "$in" => [ "Firefox", "Browser" ]}})
3386
+ it "does not use an $in query" do
3387
+ expect(selection).to eq({ dkey: { "$in" => [ "Firefox", "Browser" ]}})
3388
+ end
3792
3389
  end
3793
3390
  end
3794
3391
  end