mongoid 6.4.4 → 7.1.7

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 (942) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +13 -13
  4. data/LICENSE +1 -0
  5. data/README.md +25 -18
  6. data/Rakefile +28 -5
  7. data/lib/config/locales/en.yml +76 -50
  8. data/lib/mongoid/association/accessors.rb +417 -0
  9. data/lib/mongoid/{relations/binding.rb → association/bindable.rb} +39 -57
  10. data/lib/mongoid/association/builders.rb +93 -0
  11. data/lib/mongoid/association/constrainable.rb +46 -0
  12. data/lib/mongoid/association/depending.rb +140 -0
  13. data/lib/mongoid/{relations/eager.rb → association/eager_loadable.rb} +13 -11
  14. data/lib/mongoid/{relations → association}/embedded/batchable.rb +23 -21
  15. data/lib/mongoid/association/embedded/cyclic.rb +111 -0
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +59 -0
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +41 -0
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +124 -0
  19. data/lib/mongoid/association/embedded/embedded_in.rb +157 -0
  20. data/lib/mongoid/{relations/bindings/embedded/many.rb → association/embedded/embeds_many/binding.rb} +14 -9
  21. data/lib/mongoid/{relations/builders/embedded/many.rb → association/embedded/embeds_many/buildable.rb} +19 -7
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +555 -0
  23. data/lib/mongoid/association/embedded/embeds_many.rb +214 -0
  24. data/lib/mongoid/{relations/bindings/embedded/one.rb → association/embedded/embeds_one/binding.rb} +15 -10
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +42 -0
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +133 -0
  27. data/lib/mongoid/association/embedded/embeds_one.rb +177 -0
  28. data/lib/mongoid/association/embedded.rb +7 -0
  29. data/lib/mongoid/association/macros.rb +206 -0
  30. data/lib/mongoid/{relations → association}/many.rb +32 -59
  31. data/lib/mongoid/{relations → association}/marshalable.rb +9 -5
  32. data/lib/mongoid/association/nested/many.rb +202 -0
  33. data/lib/mongoid/association/nested/nested_buildable.rb +75 -0
  34. data/lib/mongoid/association/nested/one.rb +129 -0
  35. data/lib/mongoid/association/nested.rb +18 -0
  36. data/lib/mongoid/{relations → association}/one.rb +9 -7
  37. data/lib/mongoid/association/options.rb +155 -0
  38. data/lib/mongoid/{relations → association}/proxy.rb +59 -69
  39. data/lib/mongoid/association/referenced/auto_save.rb +82 -0
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +89 -0
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +49 -0
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +74 -0
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +138 -0
  44. data/lib/mongoid/association/referenced/belongs_to.rb +251 -0
  45. data/lib/mongoid/association/referenced/counter_cache.rb +165 -0
  46. data/lib/mongoid/association/referenced/eager.rb +184 -0
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +77 -0
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +43 -0
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +54 -0
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +319 -0
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +297 -0
  52. data/lib/mongoid/{relations/bindings/referenced/many.rb → association/referenced/has_many/binding.rb} +9 -6
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +41 -0
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +45 -0
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +517 -0
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +581 -0
  57. data/lib/mongoid/association/referenced/has_many.rb +278 -0
  58. data/lib/mongoid/{relations/bindings/referenced/one.rb → association/referenced/has_one/binding.rb} +14 -9
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +67 -0
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +37 -0
  61. data/lib/mongoid/{relations/builders/nested_attributes/one.rb → association/referenced/has_one/nested_builder.rb} +20 -18
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +120 -0
  63. data/lib/mongoid/association/referenced/has_one.rb +207 -0
  64. data/lib/mongoid/association/referenced/syncable.rb +172 -0
  65. data/lib/mongoid/association/referenced.rb +10 -0
  66. data/lib/mongoid/association/reflections.rb +70 -0
  67. data/lib/mongoid/association/relatable.rb +514 -0
  68. data/lib/mongoid/association.rb +152 -0
  69. data/lib/mongoid/atomic/modifiers.rb +24 -1
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +5 -3
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -3
  72. data/lib/mongoid/atomic/paths/embedded.rb +3 -1
  73. data/lib/mongoid/atomic/paths/root.rb +4 -2
  74. data/lib/mongoid/atomic/paths.rb +2 -0
  75. data/lib/mongoid/atomic.rb +16 -4
  76. data/lib/mongoid/attributes/dynamic.rb +18 -15
  77. data/lib/mongoid/attributes/nested.rb +29 -16
  78. data/lib/mongoid/attributes/processing.rb +10 -8
  79. data/lib/mongoid/attributes/readonly.rb +5 -5
  80. data/lib/mongoid/attributes.rb +62 -44
  81. data/lib/mongoid/cacheable.rb +3 -1
  82. data/lib/mongoid/changeable.rb +4 -2
  83. data/lib/mongoid/clients/factory.rb +3 -2
  84. data/lib/mongoid/clients/options.rb +17 -13
  85. data/lib/mongoid/clients/sessions.rb +23 -4
  86. data/lib/mongoid/clients/storage_options.rb +7 -5
  87. data/lib/mongoid/clients/validators/storage.rb +2 -0
  88. data/lib/mongoid/clients/validators.rb +2 -0
  89. data/lib/mongoid/clients.rb +2 -0
  90. data/lib/mongoid/composable.rb +8 -6
  91. data/lib/mongoid/config/environment.rb +23 -8
  92. data/lib/mongoid/config/options.rb +20 -12
  93. data/lib/mongoid/config/validators/client.rb +2 -0
  94. data/lib/mongoid/config/validators/option.rb +2 -0
  95. data/lib/mongoid/config/validators.rb +2 -0
  96. data/lib/mongoid/config.rb +53 -9
  97. data/lib/mongoid/contextual/aggregable/memory.rb +3 -1
  98. data/lib/mongoid/contextual/aggregable/mongo.rb +3 -1
  99. data/lib/mongoid/contextual/atomic.rb +24 -6
  100. data/lib/mongoid/contextual/command.rb +2 -0
  101. data/lib/mongoid/contextual/geo_near.rb +6 -4
  102. data/lib/mongoid/contextual/map_reduce.rb +5 -2
  103. data/lib/mongoid/contextual/memory.rb +23 -3
  104. data/lib/mongoid/contextual/mongo.rb +16 -9
  105. data/lib/mongoid/contextual/none.rb +2 -0
  106. data/lib/mongoid/contextual/queryable.rb +2 -0
  107. data/lib/mongoid/contextual.rb +7 -4
  108. data/lib/mongoid/copyable.rb +14 -7
  109. data/lib/mongoid/criteria/findable.rb +11 -1
  110. data/lib/mongoid/criteria/includable.rb +21 -19
  111. data/lib/mongoid/criteria/inspectable.rb +2 -0
  112. data/lib/mongoid/criteria/marshalable.rb +2 -0
  113. data/lib/mongoid/criteria/modifiable.rb +10 -3
  114. data/lib/mongoid/criteria/options.rb +4 -2
  115. data/lib/mongoid/criteria/permission.rb +2 -0
  116. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -0
  117. data/lib/mongoid/criteria/queryable/expandable.rb +93 -0
  118. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -1
  119. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +3 -1
  120. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -0
  121. data/lib/mongoid/criteria/queryable/extensions/date.rb +3 -1
  122. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +5 -6
  123. data/lib/mongoid/criteria/queryable/extensions/hash.rb +3 -1
  124. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -1
  125. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -2
  126. data/lib/mongoid/criteria/queryable/extensions/object.rb +3 -1
  127. data/lib/mongoid/criteria/queryable/extensions/range.rb +3 -1
  128. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +9 -7
  129. data/lib/mongoid/criteria/queryable/extensions/set.rb +3 -1
  130. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -2
  131. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  132. data/lib/mongoid/criteria/queryable/extensions/time.rb +4 -2
  133. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +15 -1
  134. data/lib/mongoid/criteria/queryable/extensions.rb +2 -0
  135. data/lib/mongoid/criteria/queryable/key.rb +101 -14
  136. data/lib/mongoid/criteria/queryable/macroable.rb +3 -1
  137. data/lib/mongoid/criteria/queryable/mergeable.rb +158 -15
  138. data/lib/mongoid/criteria/queryable/optional.rb +5 -3
  139. data/lib/mongoid/criteria/queryable/options.rb +2 -0
  140. data/lib/mongoid/criteria/queryable/pipeline.rb +14 -6
  141. data/lib/mongoid/criteria/queryable/selectable.rb +376 -90
  142. data/lib/mongoid/criteria/queryable/selector.rb +43 -36
  143. data/lib/mongoid/criteria/queryable/smash.rb +2 -0
  144. data/lib/mongoid/criteria/queryable/storable.rb +233 -0
  145. data/lib/mongoid/criteria/queryable.rb +7 -2
  146. data/lib/mongoid/criteria/scopable.rb +2 -0
  147. data/lib/mongoid/criteria.rb +27 -6
  148. data/lib/mongoid/document.rb +16 -4
  149. data/lib/mongoid/equality.rb +3 -2
  150. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -2
  151. data/lib/mongoid/errors/callback.rb +2 -0
  152. data/lib/mongoid/errors/criteria_argument_required.rb +19 -0
  153. data/lib/mongoid/errors/delete_restriction.rb +3 -2
  154. data/lib/mongoid/errors/document_not_destroyed.rb +2 -0
  155. data/lib/mongoid/errors/document_not_found.rb +2 -0
  156. data/lib/mongoid/errors/eager_load.rb +6 -2
  157. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -0
  158. data/lib/mongoid/errors/invalid_collection.rb +2 -0
  159. data/lib/mongoid/errors/invalid_config_option.rb +2 -0
  160. data/lib/mongoid/errors/invalid_dependent_strategy.rb +34 -0
  161. data/lib/mongoid/errors/invalid_field.rb +2 -0
  162. data/lib/mongoid/errors/invalid_field_option.rb +2 -0
  163. data/lib/mongoid/errors/invalid_find.rb +2 -0
  164. data/lib/mongoid/errors/invalid_includes.rb +2 -0
  165. data/lib/mongoid/errors/invalid_index.rb +2 -0
  166. data/lib/mongoid/errors/invalid_options.rb +4 -2
  167. data/lib/mongoid/errors/invalid_path.rb +2 -0
  168. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -0
  169. data/lib/mongoid/errors/invalid_relation.rb +4 -2
  170. data/lib/mongoid/errors/invalid_relation_option.rb +31 -0
  171. data/lib/mongoid/errors/invalid_scope.rb +2 -0
  172. data/lib/mongoid/errors/invalid_session_use.rb +2 -0
  173. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -4
  174. data/lib/mongoid/errors/invalid_storage_options.rb +2 -0
  175. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  176. data/lib/mongoid/errors/invalid_time.rb +2 -0
  177. data/lib/mongoid/errors/invalid_value.rb +2 -0
  178. data/lib/mongoid/errors/inverse_not_found.rb +3 -1
  179. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -0
  180. data/lib/mongoid/errors/mixed_relations.rb +2 -0
  181. data/lib/mongoid/errors/mongoid_error.rb +2 -0
  182. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -1
  183. data/lib/mongoid/errors/no_client_config.rb +4 -2
  184. data/lib/mongoid/errors/no_client_database.rb +2 -0
  185. data/lib/mongoid/errors/no_client_hosts.rb +2 -0
  186. data/lib/mongoid/errors/no_clients_config.rb +2 -0
  187. data/lib/mongoid/errors/no_default_client.rb +3 -1
  188. data/lib/mongoid/errors/no_environment.rb +2 -0
  189. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -0
  190. data/lib/mongoid/errors/no_metadata.rb +2 -0
  191. data/lib/mongoid/errors/no_parent.rb +2 -0
  192. data/lib/mongoid/errors/readonly_attribute.rb +2 -0
  193. data/lib/mongoid/errors/readonly_document.rb +2 -0
  194. data/lib/mongoid/errors/scope_overwrite.rb +2 -0
  195. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -0
  196. data/lib/mongoid/errors/unknown_attribute.rb +2 -0
  197. data/lib/mongoid/errors/unknown_model.rb +27 -0
  198. data/lib/mongoid/errors/unsaved_document.rb +2 -0
  199. data/lib/mongoid/errors/unsupported_javascript.rb +2 -0
  200. data/lib/mongoid/errors/validations.rb +2 -0
  201. data/lib/mongoid/errors.rb +6 -0
  202. data/lib/mongoid/evolvable.rb +3 -1
  203. data/lib/mongoid/extensions/array.rb +28 -11
  204. data/lib/mongoid/extensions/big_decimal.rb +2 -0
  205. data/lib/mongoid/extensions/boolean.rb +2 -0
  206. data/lib/mongoid/extensions/date.rb +13 -3
  207. data/lib/mongoid/extensions/date_time.rb +4 -3
  208. data/lib/mongoid/extensions/decimal128.rb +2 -0
  209. data/lib/mongoid/extensions/false_class.rb +2 -0
  210. data/lib/mongoid/extensions/float.rb +5 -3
  211. data/lib/mongoid/extensions/hash.rb +56 -11
  212. data/lib/mongoid/extensions/integer.rb +5 -3
  213. data/lib/mongoid/extensions/module.rb +2 -0
  214. data/lib/mongoid/extensions/nil_class.rb +2 -0
  215. data/lib/mongoid/extensions/object.rb +20 -8
  216. data/lib/mongoid/extensions/object_id.rb +2 -0
  217. data/lib/mongoid/extensions/range.rb +3 -0
  218. data/lib/mongoid/extensions/regexp.rb +3 -1
  219. data/lib/mongoid/extensions/set.rb +2 -0
  220. data/lib/mongoid/extensions/string.rb +23 -12
  221. data/lib/mongoid/extensions/symbol.rb +2 -0
  222. data/lib/mongoid/extensions/time.rb +14 -0
  223. data/lib/mongoid/extensions/time_with_zone.rb +14 -0
  224. data/lib/mongoid/extensions/true_class.rb +2 -0
  225. data/lib/mongoid/extensions.rb +2 -4
  226. data/lib/mongoid/factory.rb +38 -5
  227. data/lib/mongoid/fields/foreign_key.rb +8 -6
  228. data/lib/mongoid/fields/localized.rb +2 -0
  229. data/lib/mongoid/fields/standard.rb +8 -17
  230. data/lib/mongoid/fields/validators/macro.rb +17 -3
  231. data/lib/mongoid/fields/validators.rb +2 -0
  232. data/lib/mongoid/fields.rb +8 -5
  233. data/lib/mongoid/findable.rb +9 -4
  234. data/lib/mongoid/indexable/specification.rb +3 -1
  235. data/lib/mongoid/indexable/validators/options.rb +2 -0
  236. data/lib/mongoid/indexable.rb +7 -2
  237. data/lib/mongoid/inspectable.rb +3 -1
  238. data/lib/mongoid/interceptable.rb +17 -9
  239. data/lib/mongoid/loggable.rb +13 -7
  240. data/lib/mongoid/matchable/all.rb +6 -3
  241. data/lib/mongoid/matchable/and.rb +3 -1
  242. data/lib/mongoid/matchable/default.rb +73 -24
  243. data/lib/mongoid/matchable/elem_match.rb +11 -3
  244. data/lib/mongoid/matchable/eq.rb +23 -0
  245. data/lib/mongoid/matchable/exists.rb +2 -0
  246. data/lib/mongoid/matchable/gt.rb +2 -0
  247. data/lib/mongoid/matchable/gte.rb +2 -0
  248. data/lib/mongoid/matchable/in.rb +2 -0
  249. data/lib/mongoid/matchable/lt.rb +2 -0
  250. data/lib/mongoid/matchable/lte.rb +2 -0
  251. data/lib/mongoid/matchable/ne.rb +3 -1
  252. data/lib/mongoid/matchable/nin.rb +2 -0
  253. data/lib/mongoid/matchable/nor.rb +2 -1
  254. data/lib/mongoid/matchable/or.rb +2 -0
  255. data/lib/mongoid/matchable/regexp.rb +5 -2
  256. data/lib/mongoid/matchable/size.rb +2 -0
  257. data/lib/mongoid/matchable.rb +19 -16
  258. data/lib/mongoid/persistable/creatable.rb +3 -1
  259. data/lib/mongoid/persistable/deletable.rb +10 -7
  260. data/lib/mongoid/persistable/destroyable.rb +3 -1
  261. data/lib/mongoid/persistable/incrementable.rb +7 -3
  262. data/lib/mongoid/persistable/logical.rb +5 -2
  263. data/lib/mongoid/persistable/poppable.rb +3 -1
  264. data/lib/mongoid/persistable/pullable.rb +3 -1
  265. data/lib/mongoid/persistable/pushable.rb +14 -3
  266. data/lib/mongoid/persistable/renamable.rb +10 -3
  267. data/lib/mongoid/persistable/savable.rb +3 -1
  268. data/lib/mongoid/persistable/settable.rb +60 -13
  269. data/lib/mongoid/persistable/unsettable.rb +8 -3
  270. data/lib/mongoid/persistable/updatable.rb +3 -1
  271. data/lib/mongoid/persistable/upsertable.rb +3 -1
  272. data/lib/mongoid/persistable.rb +136 -19
  273. data/lib/mongoid/persistence_context.rb +47 -20
  274. data/lib/mongoid/positional.rb +3 -1
  275. data/lib/mongoid/query_cache.rb +76 -29
  276. data/lib/mongoid/railtie.rb +3 -1
  277. data/lib/mongoid/railties/controller_runtime.rb +4 -1
  278. data/lib/mongoid/railties/database.rake +9 -0
  279. data/lib/mongoid/reloadable.rb +4 -2
  280. data/lib/mongoid/scopable.rb +2 -1
  281. data/lib/mongoid/selectable.rb +3 -1
  282. data/lib/mongoid/serializable.rb +27 -17
  283. data/lib/mongoid/shardable.rb +60 -6
  284. data/lib/mongoid/stateful.rb +3 -1
  285. data/lib/mongoid/tasks/database.rake +12 -5
  286. data/lib/mongoid/tasks/database.rb +85 -0
  287. data/lib/mongoid/threaded/lifecycle.rb +2 -0
  288. data/lib/mongoid/threaded.rb +2 -0
  289. data/lib/mongoid/timestamps/created/short.rb +2 -0
  290. data/lib/mongoid/timestamps/created.rb +3 -1
  291. data/lib/mongoid/timestamps/short.rb +2 -0
  292. data/lib/mongoid/timestamps/timeless.rb +6 -2
  293. data/lib/mongoid/timestamps/updated/short.rb +2 -0
  294. data/lib/mongoid/timestamps/updated.rb +3 -1
  295. data/lib/mongoid/timestamps.rb +3 -1
  296. data/lib/mongoid/touchable.rb +110 -0
  297. data/lib/mongoid/traversable.rb +7 -5
  298. data/lib/mongoid/validatable/associated.rb +4 -2
  299. data/lib/mongoid/validatable/format.rb +2 -0
  300. data/lib/mongoid/validatable/length.rb +2 -0
  301. data/lib/mongoid/validatable/localizable.rb +2 -0
  302. data/lib/mongoid/validatable/macros.rb +3 -1
  303. data/lib/mongoid/validatable/presence.rb +6 -4
  304. data/lib/mongoid/validatable/queryable.rb +2 -0
  305. data/lib/mongoid/validatable/uniqueness.rb +9 -7
  306. data/lib/mongoid/validatable.rb +15 -13
  307. data/lib/mongoid/version.rb +3 -1
  308. data/lib/mongoid.rb +11 -2
  309. data/lib/rails/generators/mongoid/config/config_generator.rb +2 -0
  310. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +44 -26
  311. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -1
  312. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  313. data/lib/rails/generators/mongoid_generator.rb +2 -0
  314. data/lib/rails/mongoid.rb +4 -2
  315. data/lib/support/ruby_version.rb +3 -0
  316. data/spec/README.md +18 -0
  317. data/spec/app/models/account.rb +3 -0
  318. data/spec/app/models/acolyte.rb +3 -0
  319. data/spec/app/models/actor.rb +3 -0
  320. data/spec/app/models/actress.rb +3 -0
  321. data/spec/app/models/address.rb +3 -0
  322. data/spec/app/models/address_component.rb +3 -0
  323. data/spec/app/models/address_number.rb +3 -0
  324. data/spec/app/models/agency.rb +3 -0
  325. data/spec/app/models/agent.rb +3 -0
  326. data/spec/app/models/album.rb +3 -0
  327. data/spec/app/models/alert.rb +3 -0
  328. data/spec/app/models/animal.rb +5 -1
  329. data/spec/app/models/answer.rb +3 -0
  330. data/spec/app/models/appointment.rb +3 -0
  331. data/spec/app/models/array_field.rb +1 -0
  332. data/spec/app/models/article.rb +3 -0
  333. data/spec/app/models/artist.rb +3 -0
  334. data/spec/app/models/artwork.rb +3 -0
  335. data/spec/app/models/audio.rb +3 -0
  336. data/spec/app/models/augmentation.rb +3 -0
  337. data/spec/app/models/author.rb +3 -0
  338. data/spec/app/models/baby.rb +3 -0
  339. data/spec/app/models/band.rb +3 -0
  340. data/spec/app/models/bar.rb +3 -0
  341. data/spec/app/models/basic.rb +3 -0
  342. data/spec/app/models/bed.rb +3 -0
  343. data/spec/app/models/big_palette.rb +3 -0
  344. data/spec/app/models/birthday.rb +3 -0
  345. data/spec/app/models/bomb.rb +4 -1
  346. data/spec/app/models/book.rb +3 -0
  347. data/spec/app/models/breed.rb +3 -0
  348. data/spec/app/models/browser.rb +3 -0
  349. data/spec/app/models/building.rb +3 -0
  350. data/spec/app/models/building_address.rb +3 -0
  351. data/spec/app/models/bus.rb +3 -0
  352. data/spec/app/models/business.rb +3 -0
  353. data/spec/app/models/callback_test.rb +3 -0
  354. data/spec/app/models/canvas.rb +3 -0
  355. data/spec/app/models/car.rb +3 -0
  356. data/spec/app/models/cat.rb +3 -0
  357. data/spec/app/models/category.rb +3 -0
  358. data/spec/app/models/child.rb +3 -0
  359. data/spec/app/models/child_doc.rb +3 -0
  360. data/spec/app/models/church.rb +3 -0
  361. data/spec/app/models/circle.rb +3 -0
  362. data/spec/app/models/circuit.rb +3 -0
  363. data/spec/app/models/circus.rb +3 -0
  364. data/spec/app/models/code.rb +3 -0
  365. data/spec/app/models/coding/pull_request.rb +12 -0
  366. data/spec/app/models/coding.rb +4 -0
  367. data/spec/app/models/comment.rb +3 -0
  368. data/spec/app/models/company.rb +3 -0
  369. data/spec/app/models/consumption_period.rb +3 -0
  370. data/spec/app/models/contextable_item.rb +3 -0
  371. data/spec/app/models/contractor.rb +3 -0
  372. data/spec/app/models/cookie.rb +3 -0
  373. data/spec/app/models/country_code.rb +3 -0
  374. data/spec/app/models/courier_job.rb +3 -0
  375. data/spec/app/models/customer.rb +11 -0
  376. data/spec/app/models/customer_address.rb +12 -0
  377. data/spec/app/models/definition.rb +3 -0
  378. data/spec/app/models/delegating_patient.rb +16 -0
  379. data/spec/app/models/description.rb +3 -0
  380. data/spec/app/models/dictionary.rb +9 -0
  381. data/spec/app/models/division.rb +3 -0
  382. data/spec/app/models/doctor.rb +3 -0
  383. data/spec/app/models/dog.rb +3 -0
  384. data/spec/app/models/dokument.rb +3 -0
  385. data/spec/app/models/draft.rb +3 -0
  386. data/spec/app/models/dragon.rb +3 -0
  387. data/spec/app/models/driver.rb +3 -0
  388. data/spec/app/models/drug.rb +3 -0
  389. data/spec/app/models/dungeon.rb +3 -0
  390. data/spec/app/models/edit.rb +3 -0
  391. data/spec/app/models/email.rb +3 -0
  392. data/spec/app/models/employer.rb +3 -0
  393. data/spec/app/models/entry.rb +3 -0
  394. data/spec/app/models/eraser.rb +3 -0
  395. data/spec/app/models/even.rb +3 -0
  396. data/spec/app/models/event.rb +3 -0
  397. data/spec/app/models/exhibition.rb +3 -0
  398. data/spec/app/models/exhibitor.rb +3 -0
  399. data/spec/app/models/explosion.rb +3 -0
  400. data/spec/app/models/eye.rb +3 -0
  401. data/spec/app/models/eye_bowl.rb +3 -0
  402. data/spec/app/models/face.rb +3 -0
  403. data/spec/app/models/favorite.rb +3 -0
  404. data/spec/app/models/filesystem.rb +3 -0
  405. data/spec/app/models/fire_hydrant.rb +3 -0
  406. data/spec/app/models/firefox.rb +3 -0
  407. data/spec/app/models/fish.rb +3 -0
  408. data/spec/app/models/folder.rb +3 -0
  409. data/spec/app/models/folder_item.rb +3 -0
  410. data/spec/app/models/fruits.rb +3 -0
  411. data/spec/app/models/game.rb +3 -0
  412. data/spec/app/models/ghost.rb +3 -0
  413. data/spec/app/models/home.rb +3 -0
  414. data/spec/app/models/house.rb +3 -0
  415. data/spec/app/models/html_writer.rb +3 -0
  416. data/spec/app/models/id_key.rb +3 -0
  417. data/spec/app/models/image.rb +3 -0
  418. data/spec/app/models/implant.rb +3 -0
  419. data/spec/app/models/item.rb +3 -0
  420. data/spec/app/models/jar.rb +3 -0
  421. data/spec/app/models/kaleidoscope.rb +3 -0
  422. data/spec/app/models/kangaroo.rb +4 -1
  423. data/spec/app/models/label.rb +3 -0
  424. data/spec/app/models/language.rb +3 -0
  425. data/spec/app/models/lat_lng.rb +3 -0
  426. data/spec/app/models/league.rb +3 -0
  427. data/spec/app/models/learner.rb +3 -0
  428. data/spec/app/models/line_item.rb +3 -0
  429. data/spec/app/models/location.rb +3 -0
  430. data/spec/app/models/login.rb +3 -0
  431. data/spec/app/models/manufacturer.rb +3 -0
  432. data/spec/app/models/meat.rb +3 -0
  433. data/spec/app/models/membership.rb +3 -0
  434. data/spec/app/models/message.rb +4 -1
  435. data/spec/app/models/minim.rb +7 -0
  436. data/spec/app/models/mixed_drink.rb +3 -0
  437. data/spec/app/models/movie.rb +3 -0
  438. data/spec/app/models/my_hash.rb +3 -0
  439. data/spec/app/models/name.rb +3 -0
  440. data/spec/app/models/name_only.rb +9 -0
  441. data/spec/app/models/node.rb +3 -0
  442. data/spec/app/models/note.rb +3 -0
  443. data/spec/app/models/odd.rb +3 -0
  444. data/spec/app/models/ordered_post.rb +3 -0
  445. data/spec/app/models/ordered_preference.rb +3 -0
  446. data/spec/app/models/oscar.rb +3 -0
  447. data/spec/app/models/other_owner_object.rb +5 -0
  448. data/spec/app/models/override.rb +3 -0
  449. data/spec/app/models/ownable.rb +3 -0
  450. data/spec/app/models/owner.rb +3 -0
  451. data/spec/app/models/pack.rb +3 -0
  452. data/spec/app/models/page.rb +3 -0
  453. data/spec/app/models/page_question.rb +3 -0
  454. data/spec/app/models/palette.rb +3 -0
  455. data/spec/app/models/parent.rb +3 -0
  456. data/spec/app/models/parent_doc.rb +3 -0
  457. data/spec/app/models/passport.rb +4 -0
  458. data/spec/app/models/patient.rb +3 -0
  459. data/spec/app/models/pdf_writer.rb +3 -0
  460. data/spec/app/models/pencil.rb +3 -0
  461. data/spec/app/models/person.rb +10 -2
  462. data/spec/app/models/pet.rb +3 -0
  463. data/spec/app/models/pet_owner.rb +3 -0
  464. data/spec/app/models/phone.rb +4 -0
  465. data/spec/app/models/pizza.rb +3 -0
  466. data/spec/app/models/player.rb +3 -0
  467. data/spec/app/models/post.rb +3 -0
  468. data/spec/app/models/post_genre.rb +3 -0
  469. data/spec/app/models/powerup.rb +3 -0
  470. data/spec/app/models/preference.rb +3 -0
  471. data/spec/app/models/princess.rb +3 -0
  472. data/spec/app/models/product.rb +3 -0
  473. data/spec/app/models/profile.rb +3 -0
  474. data/spec/app/models/pronunciation.rb +3 -0
  475. data/spec/app/models/pub.rb +3 -0
  476. data/spec/app/models/publication/encyclopedia.rb +12 -0
  477. data/spec/app/models/publication/review.rb +14 -0
  478. data/spec/app/models/publication.rb +5 -0
  479. data/spec/app/models/purchase.rb +3 -0
  480. data/spec/app/models/question.rb +3 -0
  481. data/spec/app/models/quiz.rb +3 -0
  482. data/spec/app/models/rating.rb +3 -0
  483. data/spec/app/models/record.rb +3 -0
  484. data/spec/app/models/registry.rb +3 -0
  485. data/spec/app/models/role.rb +3 -0
  486. data/spec/app/models/root_category.rb +3 -0
  487. data/spec/app/models/sandwich.rb +3 -0
  488. data/spec/app/models/scheduler.rb +3 -0
  489. data/spec/app/models/seo.rb +3 -0
  490. data/spec/app/models/series.rb +4 -0
  491. data/spec/app/models/server.rb +3 -0
  492. data/spec/app/models/service.rb +3 -0
  493. data/spec/app/models/shape.rb +3 -0
  494. data/spec/app/models/shelf.rb +3 -0
  495. data/spec/app/models/shipment_address.rb +4 -0
  496. data/spec/app/models/shipping_container.rb +3 -0
  497. data/spec/app/models/shipping_pack.rb +3 -0
  498. data/spec/app/models/shop.rb +3 -0
  499. data/spec/app/models/short_agent.rb +3 -0
  500. data/spec/app/models/short_quiz.rb +3 -0
  501. data/spec/app/models/simple.rb +3 -0
  502. data/spec/app/models/slave.rb +3 -0
  503. data/spec/app/models/song.rb +3 -0
  504. data/spec/app/models/sound.rb +3 -0
  505. data/spec/app/models/square.rb +3 -0
  506. data/spec/app/models/staff.rb +3 -0
  507. data/spec/app/models/store_as_dup_test1.rb +3 -0
  508. data/spec/app/models/store_as_dup_test2.rb +3 -0
  509. data/spec/app/models/store_as_dup_test3.rb +8 -0
  510. data/spec/app/models/store_as_dup_test4.rb +8 -0
  511. data/spec/app/models/strategy.rb +3 -0
  512. data/spec/app/models/sub_item.rb +3 -0
  513. data/spec/app/models/subscription.rb +3 -0
  514. data/spec/app/models/survey.rb +3 -0
  515. data/spec/app/models/symptom.rb +3 -0
  516. data/spec/app/models/tag.rb +3 -0
  517. data/spec/app/models/target.rb +3 -0
  518. data/spec/app/models/template.rb +3 -0
  519. data/spec/app/models/thing.rb +3 -0
  520. data/spec/app/models/title.rb +3 -0
  521. data/spec/app/models/tool.rb +3 -0
  522. data/spec/app/models/topping.rb +3 -0
  523. data/spec/app/models/track.rb +3 -0
  524. data/spec/app/models/translation.rb +3 -0
  525. data/spec/app/models/tree.rb +3 -0
  526. data/spec/app/models/truck.rb +3 -0
  527. data/spec/app/models/updatable.rb +8 -0
  528. data/spec/app/models/user.rb +3 -0
  529. data/spec/app/models/user_account.rb +3 -0
  530. data/spec/app/models/validation_callback.rb +3 -0
  531. data/spec/app/models/vehicle.rb +3 -0
  532. data/spec/app/models/version.rb +3 -0
  533. data/spec/app/models/vertex.rb +9 -0
  534. data/spec/app/models/vet_visit.rb +3 -0
  535. data/spec/app/models/video.rb +3 -0
  536. data/spec/app/models/video_game.rb +3 -0
  537. data/spec/app/models/weapon.rb +3 -0
  538. data/spec/app/models/wiki_page.rb +5 -1
  539. data/spec/app/models/word.rb +3 -0
  540. data/spec/app/models/word_origin.rb +3 -0
  541. data/spec/app/models/writer.rb +3 -0
  542. data/spec/config/mongoid.yml +14 -3
  543. data/spec/integration/app_spec.rb +287 -0
  544. data/spec/integration/associations/belongs_to_spec.rb +16 -0
  545. data/spec/integration/associations/embedded_spec.rb +175 -0
  546. data/spec/integration/associations/embeds_many_spec.rb +24 -0
  547. data/spec/integration/associations/embeds_one_spec.rb +24 -0
  548. data/spec/integration/associations/foreign_key_spec.rb +99 -0
  549. data/spec/integration/associations/foreign_key_spec_models.rb +65 -0
  550. data/spec/integration/associations/has_many_spec.rb +76 -0
  551. data/spec/integration/associations/has_one_spec.rb +76 -0
  552. data/spec/integration/associations/reverse_population_spec.rb +35 -0
  553. data/spec/integration/associations/reverse_population_spec_models.rb +37 -0
  554. data/spec/integration/bson_regexp_raw_spec.rb +20 -0
  555. data/spec/integration/callbacks_models.rb +49 -0
  556. data/spec/integration/callbacks_spec.rb +216 -0
  557. data/spec/integration/criteria/date_field_spec.rb +41 -0
  558. data/spec/integration/criteria/default_scope_spec.rb +21 -0
  559. data/spec/integration/criteria/logical_spec.rb +94 -0
  560. data/spec/integration/criteria/time_with_zone_spec.rb +32 -0
  561. data/spec/integration/document_spec.rb +22 -0
  562. data/spec/integration/i18n_fallbacks_spec.rb +90 -0
  563. data/spec/integration/matchable_spec.rb +680 -0
  564. data/spec/integration/shardable_spec.rb +149 -0
  565. data/spec/lite_spec_helper.rb +75 -0
  566. data/spec/mongoid/{relations → association}/accessors_spec.rb +281 -64
  567. data/spec/mongoid/{relations → association}/auto_save_spec.rb +63 -12
  568. data/spec/mongoid/{relations → association}/builders_spec.rb +4 -1
  569. data/spec/mongoid/association/constrainable_spec.rb +118 -0
  570. data/spec/mongoid/{relations → association}/counter_cache_spec.rb +4 -1
  571. data/spec/mongoid/association/depending_spec.rb +869 -0
  572. data/spec/mongoid/{relations → association}/eager_spec.rb +15 -12
  573. data/spec/mongoid/{relations → association/embedded}/cyclic_spec.rb +4 -1
  574. data/spec/mongoid/{relations → association}/embedded/dirty_spec.rb +3 -0
  575. data/spec/mongoid/{relations/bindings/embedded/in_spec.rb → association/embedded/embedded_in/binding_spec.rb} +16 -13
  576. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +37 -0
  577. data/spec/mongoid/{relations/embedded/in_spec.rb → association/embedded/embedded_in/proxy_spec.rb} +58 -77
  578. data/spec/mongoid/association/embedded/embedded_in_spec.rb +904 -0
  579. data/spec/mongoid/{relations/bindings/embedded/many_spec.rb → association/embedded/embeds_many/binding_spec.rb} +6 -3
  580. data/spec/mongoid/{relations/builders/embedded/many_spec.rb → association/embedded/embeds_many/buildable_spec.rb} +20 -45
  581. data/spec/mongoid/{relations/embedded/many_spec.rb → association/embedded/embeds_many/proxy_spec.rb} +127 -182
  582. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  583. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +52 -0
  584. data/spec/mongoid/association/embedded/embeds_many_spec.rb +865 -0
  585. data/spec/mongoid/{relations/bindings/embedded/one_spec.rb → association/embedded/embeds_one/binding_spec.rb} +7 -4
  586. data/spec/mongoid/{relations/builders/embedded/one_spec.rb → association/embedded/embeds_one/buildable_spec.rb} +17 -34
  587. data/spec/mongoid/{relations/embedded/one_spec.rb → association/embedded/embeds_one/proxy_spec.rb} +42 -84
  588. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +9 -0
  589. data/spec/mongoid/association/embedded/embeds_one_models.rb +54 -0
  590. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +29 -0
  591. data/spec/mongoid/association/embedded/embeds_one_spec.rb +957 -0
  592. data/spec/mongoid/{relations → association}/macros_spec.rb +151 -73
  593. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/many_spec.rb +19 -19
  594. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/one_spec.rb +20 -20
  595. data/spec/mongoid/association/options_spec.rb +1324 -0
  596. data/spec/mongoid/{relations → association}/polymorphic_spec.rb +69 -34
  597. data/spec/mongoid/{relations/bindings/referenced/in_spec.rb → association/referenced/belongs_to/binding_spec.rb} +10 -7
  598. data/spec/mongoid/{relations/builders/referenced/in_spec.rb → association/referenced/belongs_to/buildable_spec.rb} +49 -79
  599. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +377 -0
  600. data/spec/mongoid/{relations/referenced/in_spec.rb → association/referenced/belongs_to/proxy_spec.rb} +60 -91
  601. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +38 -0
  602. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2026 -0
  603. data/spec/mongoid/{relations/bindings/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/binding_spec.rb} +8 -5
  604. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +124 -0
  605. data/spec/mongoid/{relations/eager/has_and_belongs_to_many_spec.rb → association/referenced/has_and_belongs_to_many/eager_spec.rb} +42 -7
  606. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +77 -0
  607. data/spec/mongoid/{relations/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/proxy_spec.rb} +283 -112
  608. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +50 -0
  609. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +40 -0
  610. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1051 -0
  611. data/spec/mongoid/{relations/bindings/referenced/many_spec.rb → association/referenced/has_many/binding_spec.rb} +8 -5
  612. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +122 -0
  613. data/spec/mongoid/{relations/eager/has_many_spec.rb → association/referenced/has_many/eager_spec.rb} +43 -13
  614. data/spec/mongoid/{relations/targets → association/referenced/has_many}/enumerable_spec.rb +230 -1
  615. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +24 -0
  616. data/spec/mongoid/{relations/referenced/many_spec.rb → association/referenced/has_many/proxy_spec.rb} +33 -94
  617. data/spec/mongoid/association/referenced/has_many_models.rb +40 -0
  618. data/spec/mongoid/association/referenced/has_many_query_spec.rb +38 -0
  619. data/spec/mongoid/association/referenced/has_many_spec.rb +1228 -0
  620. data/spec/mongoid/{relations/bindings/referenced/one_spec.rb → association/referenced/has_one/binding_spec.rb} +7 -4
  621. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +116 -0
  622. data/spec/mongoid/{relations/eager/has_one_spec.rb → association/referenced/has_one/eager_spec.rb} +27 -12
  623. data/spec/mongoid/{relations/referenced/one_spec.rb → association/referenced/has_one/proxy_spec.rb} +12 -109
  624. data/spec/mongoid/association/referenced/has_one_models.rb +51 -0
  625. data/spec/mongoid/association/referenced/has_one_query_spec.rb +38 -0
  626. data/spec/mongoid/association/referenced/has_one_spec.rb +1363 -0
  627. data/spec/mongoid/{relations → association}/reflections_spec.rb +4 -12
  628. data/spec/mongoid/{relations/synchronization_spec.rb → association/syncable_spec.rb} +7 -2
  629. data/spec/mongoid/{relations_spec.rb → association_spec.rb} +4 -1
  630. data/spec/mongoid/atomic/modifiers_spec.rb +5 -2
  631. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +3 -0
  632. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +3 -0
  633. data/spec/mongoid/atomic/paths/root_spec.rb +3 -0
  634. data/spec/mongoid/atomic/paths_spec.rb +44 -0
  635. data/spec/mongoid/atomic_spec.rb +7 -4
  636. data/spec/mongoid/attributes/dynamic_spec.rb +153 -0
  637. data/spec/mongoid/attributes/nested_spec.rb +32 -11
  638. data/spec/mongoid/attributes/readonly_spec.rb +83 -125
  639. data/spec/mongoid/attributes_spec.rb +60 -9
  640. data/spec/mongoid/cacheable_spec.rb +3 -0
  641. data/spec/mongoid/changeable_spec.rb +26 -0
  642. data/spec/mongoid/clients/factory_spec.rb +57 -33
  643. data/spec/mongoid/clients/options_spec.rb +81 -56
  644. data/spec/mongoid/clients/sessions_spec.rb +24 -8
  645. data/spec/mongoid/clients/transactions_spec.rb +393 -0
  646. data/spec/mongoid/clients_spec.rb +73 -10
  647. data/spec/mongoid/composable_spec.rb +3 -0
  648. data/spec/mongoid/config/environment_spec.rb +3 -0
  649. data/spec/mongoid/config/options_spec.rb +23 -3
  650. data/spec/mongoid/config_spec.rb +66 -1
  651. data/spec/mongoid/contextual/aggregable/memory_spec.rb +3 -0
  652. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +3 -0
  653. data/spec/mongoid/contextual/atomic_spec.rb +120 -10
  654. data/spec/mongoid/contextual/geo_near_spec.rb +15 -2
  655. data/spec/mongoid/contextual/map_reduce_spec.rb +23 -5
  656. data/spec/mongoid/contextual/memory_spec.rb +22 -0
  657. data/spec/mongoid/contextual/mongo_spec.rb +113 -57
  658. data/spec/mongoid/contextual/none_spec.rb +3 -0
  659. data/spec/mongoid/copyable_spec.rb +93 -6
  660. data/spec/mongoid/copyable_spec_models.rb +20 -0
  661. data/spec/mongoid/criteria/findable_spec.rb +58 -0
  662. data/spec/mongoid/criteria/inspectable_spec.rb +3 -0
  663. data/spec/mongoid/criteria/marshalable_spec.rb +3 -0
  664. data/spec/mongoid/criteria/modifiable_spec.rb +180 -4
  665. data/spec/mongoid/criteria/options_spec.rb +3 -0
  666. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -0
  667. data/spec/mongoid/criteria/queryable/expandable_spec.rb +135 -0
  668. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +3 -0
  669. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -0
  670. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +3 -0
  671. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -0
  672. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +3 -0
  673. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +36 -17
  674. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +3 -0
  675. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +3 -0
  676. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +3 -0
  677. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +3 -0
  678. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +3 -0
  679. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
  680. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +3 -0
  681. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +3 -0
  682. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +4 -1
  683. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +10 -7
  684. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +3 -0
  685. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +47 -1
  686. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +3 -0
  687. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +43 -23
  688. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +31 -1
  689. data/spec/mongoid/criteria/queryable/key_spec.rb +51 -6
  690. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +48 -12
  691. data/spec/mongoid/criteria/queryable/optional_spec.rb +3 -0
  692. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -0
  693. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +15 -0
  694. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -0
  695. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1865 -0
  696. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1007 -2389
  697. data/spec/mongoid/criteria/queryable/selector_spec.rb +40 -0
  698. data/spec/mongoid/criteria/queryable/smash_spec.rb +3 -0
  699. data/spec/mongoid/criteria/queryable/storable_spec.rb +190 -0
  700. data/spec/mongoid/criteria/scopable_spec.rb +3 -0
  701. data/spec/mongoid/criteria_spec.rb +108 -19
  702. data/spec/mongoid/document_fields_spec.rb +88 -0
  703. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  704. data/spec/mongoid/document_query_spec.rb +39 -0
  705. data/spec/mongoid/document_spec.rb +32 -4
  706. data/spec/mongoid/equality_spec.rb +3 -0
  707. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +6 -3
  708. data/spec/mongoid/errors/callback_spec.rb +3 -0
  709. data/spec/mongoid/errors/delete_restriction_spec.rb +3 -0
  710. data/spec/mongoid/errors/document_not_destroyed_spec.rb +3 -0
  711. data/spec/mongoid/errors/document_not_found_spec.rb +3 -0
  712. data/spec/mongoid/errors/eager_load_spec.rb +3 -0
  713. data/spec/mongoid/errors/invalid_collection_spec.rb +3 -0
  714. data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -0
  715. data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -0
  716. data/spec/mongoid/errors/invalid_field_spec.rb +3 -0
  717. data/spec/mongoid/errors/invalid_find_spec.rb +3 -0
  718. data/spec/mongoid/errors/invalid_includes_spec.rb +3 -0
  719. data/spec/mongoid/errors/invalid_index_spec.rb +3 -0
  720. data/spec/mongoid/errors/invalid_options_spec.rb +5 -2
  721. data/spec/mongoid/errors/invalid_path_spec.rb +3 -0
  722. data/spec/mongoid/errors/invalid_relation_spec.rb +5 -2
  723. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -0
  724. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -0
  725. data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -0
  726. data/spec/mongoid/errors/invalid_time_spec.rb +3 -0
  727. data/spec/mongoid/errors/inverse_not_found_spec.rb +4 -1
  728. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +3 -0
  729. data/spec/mongoid/errors/mixed_relations_spec.rb +3 -0
  730. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -0
  731. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +6 -3
  732. data/spec/mongoid/errors/no_client_config_spec.rb +5 -2
  733. data/spec/mongoid/errors/no_client_database_spec.rb +6 -3
  734. data/spec/mongoid/errors/no_client_hosts_spec.rb +6 -3
  735. data/spec/mongoid/errors/no_clients_config_spec.rb +3 -0
  736. data/spec/mongoid/errors/no_environment_spec.rb +3 -0
  737. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -0
  738. data/spec/mongoid/errors/no_metadata_spec.rb +5 -2
  739. data/spec/mongoid/errors/no_parent_spec.rb +4 -1
  740. data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -0
  741. data/spec/mongoid/errors/readonly_document_spec.rb +3 -0
  742. data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -0
  743. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -0
  744. data/spec/mongoid/errors/unknown_attribute_spec.rb +3 -0
  745. data/spec/mongoid/errors/unsaved_document_spec.rb +4 -1
  746. data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -0
  747. data/spec/mongoid/errors/validations_spec.rb +3 -0
  748. data/spec/mongoid/extensions/array_spec.rb +37 -58
  749. data/spec/mongoid/extensions/big_decimal_spec.rb +3 -0
  750. data/spec/mongoid/extensions/binary_spec.rb +3 -0
  751. data/spec/mongoid/extensions/boolean_spec.rb +3 -0
  752. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +336 -0
  753. data/spec/mongoid/extensions/date_spec.rb +9 -160
  754. data/spec/mongoid/extensions/date_time_spec.rb +18 -60
  755. data/spec/mongoid/extensions/decimal128_spec.rb +3 -0
  756. data/spec/mongoid/extensions/false_class_spec.rb +3 -0
  757. data/spec/mongoid/extensions/float_spec.rb +18 -3
  758. data/spec/mongoid/extensions/hash_spec.rb +124 -1
  759. data/spec/mongoid/extensions/integer_spec.rb +15 -2
  760. data/spec/mongoid/extensions/module_spec.rb +3 -0
  761. data/spec/mongoid/extensions/nil_class_spec.rb +3 -0
  762. data/spec/mongoid/extensions/object_id_spec.rb +3 -0
  763. data/spec/mongoid/extensions/object_spec.rb +21 -35
  764. data/spec/mongoid/extensions/range_spec.rb +10 -0
  765. data/spec/mongoid/extensions/regexp_spec.rb +3 -0
  766. data/spec/mongoid/extensions/set_spec.rb +3 -0
  767. data/spec/mongoid/extensions/string_spec.rb +95 -33
  768. data/spec/mongoid/extensions/symbol_spec.rb +3 -0
  769. data/spec/mongoid/extensions/time_spec.rb +30 -0
  770. data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -0
  771. data/spec/mongoid/extensions/true_class_spec.rb +3 -0
  772. data/spec/mongoid/extensions_spec.rb +3 -0
  773. data/spec/mongoid/factory_spec.rb +46 -1
  774. data/spec/mongoid/fields/foreign_key_spec.rb +27 -32
  775. data/spec/mongoid/fields/localized_spec.rb +3 -0
  776. data/spec/mongoid/fields/standard_spec.rb +3 -0
  777. data/spec/mongoid/fields_spec.rb +42 -1
  778. data/spec/mongoid/findable_spec.rb +4 -1
  779. data/spec/mongoid/indexable/specification_spec.rb +3 -0
  780. data/spec/mongoid/indexable_spec.rb +27 -12
  781. data/spec/mongoid/inspectable_spec.rb +3 -0
  782. data/spec/mongoid/interceptable_spec.rb +87 -1
  783. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  784. data/spec/mongoid/loggable_spec.rb +3 -0
  785. data/spec/mongoid/matchable/all_spec.rb +3 -0
  786. data/spec/mongoid/matchable/and_spec.rb +3 -0
  787. data/spec/mongoid/matchable/default_spec.rb +13 -3
  788. data/spec/mongoid/matchable/elem_match_spec.rb +23 -0
  789. data/spec/mongoid/matchable/eq_spec.rb +49 -0
  790. data/spec/mongoid/matchable/exists_spec.rb +3 -0
  791. data/spec/mongoid/matchable/gt_spec.rb +3 -0
  792. data/spec/mongoid/matchable/gte_spec.rb +3 -0
  793. data/spec/mongoid/matchable/in_spec.rb +3 -0
  794. data/spec/mongoid/matchable/lt_spec.rb +3 -0
  795. data/spec/mongoid/matchable/lte_spec.rb +3 -0
  796. data/spec/mongoid/matchable/ne_spec.rb +3 -0
  797. data/spec/mongoid/matchable/nin_spec.rb +3 -0
  798. data/spec/mongoid/matchable/nor_spec.rb +1 -0
  799. data/spec/mongoid/matchable/or_spec.rb +3 -0
  800. data/spec/mongoid/matchable/regexp_spec.rb +5 -2
  801. data/spec/mongoid/matchable/size_spec.rb +3 -0
  802. data/spec/mongoid/matchable_spec.rb +5 -2
  803. data/spec/mongoid/persistable/creatable_spec.rb +3 -0
  804. data/spec/mongoid/persistable/deletable_spec.rb +3 -0
  805. data/spec/mongoid/persistable/destroyable_spec.rb +3 -0
  806. data/spec/mongoid/persistable/incrementable_spec.rb +17 -0
  807. data/spec/mongoid/persistable/logical_spec.rb +17 -0
  808. data/spec/mongoid/persistable/poppable_spec.rb +17 -0
  809. data/spec/mongoid/persistable/pullable_spec.rb +31 -0
  810. data/spec/mongoid/persistable/pushable_spec.rb +86 -1
  811. data/spec/mongoid/persistable/renamable_spec.rb +17 -0
  812. data/spec/mongoid/persistable/savable_spec.rb +5 -2
  813. data/spec/mongoid/persistable/settable_spec.rb +112 -10
  814. data/spec/mongoid/persistable/unsettable_spec.rb +17 -0
  815. data/spec/mongoid/persistable/updatable_spec.rb +3 -0
  816. data/spec/mongoid/persistable/upsertable_spec.rb +3 -0
  817. data/spec/mongoid/persistable_spec.rb +106 -14
  818. data/spec/mongoid/persistence_context_spec.rb +4 -1
  819. data/spec/mongoid/positional_spec.rb +3 -0
  820. data/spec/mongoid/query_cache_middleware_spec.rb +48 -0
  821. data/spec/mongoid/query_cache_spec.rb +131 -65
  822. data/spec/mongoid/relations/proxy_spec.rb +127 -124
  823. data/spec/mongoid/reloadable_spec.rb +3 -0
  824. data/spec/mongoid/scopable_spec.rb +5 -1
  825. data/spec/mongoid/selectable_spec.rb +3 -0
  826. data/spec/mongoid/serializable_spec.rb +132 -18
  827. data/spec/mongoid/shardable_models.rb +61 -0
  828. data/spec/mongoid/shardable_spec.rb +104 -28
  829. data/spec/mongoid/stateful_spec.rb +3 -0
  830. data/spec/mongoid/tasks/database_rake_spec.rb +16 -13
  831. data/spec/mongoid/tasks/database_spec.rb +4 -1
  832. data/spec/mongoid/threaded_spec.rb +3 -0
  833. data/spec/mongoid/timestamps/created/short_spec.rb +3 -0
  834. data/spec/mongoid/timestamps/created_spec.rb +3 -0
  835. data/spec/mongoid/timestamps/timeless_spec.rb +3 -0
  836. data/spec/mongoid/timestamps/updated/short_spec.rb +3 -0
  837. data/spec/mongoid/timestamps/updated_spec.rb +3 -0
  838. data/spec/mongoid/timestamps_spec.rb +3 -0
  839. data/spec/mongoid/{relations/touchable_spec.rb → touchable_spec.rb} +89 -4
  840. data/spec/mongoid/traversable_spec.rb +3 -0
  841. data/spec/mongoid/validatable/associated_spec.rb +4 -1
  842. data/spec/mongoid/validatable/format_spec.rb +3 -0
  843. data/spec/mongoid/validatable/length_spec.rb +3 -0
  844. data/spec/mongoid/validatable/numericality_spec.rb +3 -0
  845. data/spec/mongoid/validatable/presence_spec.rb +10 -6
  846. data/spec/mongoid/validatable/uniqueness_spec.rb +36 -6
  847. data/spec/mongoid/validatable_spec.rb +4 -1
  848. data/spec/mongoid_spec.rb +3 -0
  849. data/spec/rails/controller_extension/controller_runtime_spec.rb +4 -1
  850. data/spec/rails/mongoid_spec.rb +5 -2
  851. data/spec/shared/LICENSE +20 -0
  852. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  853. data/spec/shared/lib/mrss/cluster_config.rb +211 -0
  854. data/spec/shared/lib/mrss/constraints.rb +330 -0
  855. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  856. data/spec/shared/lib/mrss/lite_constraints.rb +175 -0
  857. data/spec/shared/lib/mrss/server_version_registry.rb +69 -0
  858. data/spec/shared/lib/mrss/spec_organizer.rb +149 -0
  859. data/spec/shared/share/Dockerfile.erb +229 -0
  860. data/spec/shared/shlib/distro.sh +73 -0
  861. data/spec/shared/shlib/server.sh +270 -0
  862. data/spec/shared/shlib/set_env.sh +128 -0
  863. data/spec/spec_helper.rb +56 -55
  864. data/spec/support/authorization.rb +3 -0
  865. data/spec/support/child_process_helper.rb +76 -0
  866. data/spec/support/cluster_config.rb +158 -0
  867. data/spec/support/constraints.rb +256 -0
  868. data/spec/support/expectations.rb +22 -3
  869. data/spec/support/helpers.rb +11 -0
  870. data/spec/support/lite_constraints.rb +22 -0
  871. data/spec/support/macros.rb +21 -0
  872. data/spec/support/session_registry.rb +50 -0
  873. data/spec/support/shared/time.rb +54 -0
  874. data/spec/support/spec_config.rb +50 -0
  875. data.tar.gz.sig +2 -1
  876. metadata +737 -550
  877. metadata.gz.sig +0 -0
  878. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  879. data/lib/mongoid/relations/accessors.rb +0 -267
  880. data/lib/mongoid/relations/auto_save.rb +0 -94
  881. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  882. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  883. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  884. data/lib/mongoid/relations/bindings.rb +0 -9
  885. data/lib/mongoid/relations/builder.rb +0 -57
  886. data/lib/mongoid/relations/builders/embedded/in.rb +0 -29
  887. data/lib/mongoid/relations/builders/embedded/one.rb +0 -30
  888. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  889. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  890. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  891. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  892. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  893. data/lib/mongoid/relations/builders.rb +0 -106
  894. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  895. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  896. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  897. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  898. data/lib/mongoid/relations/cascading.rb +0 -56
  899. data/lib/mongoid/relations/constraint.rb +0 -55
  900. data/lib/mongoid/relations/conversions.rb +0 -34
  901. data/lib/mongoid/relations/counter_cache.rb +0 -160
  902. data/lib/mongoid/relations/cyclic.rb +0 -107
  903. data/lib/mongoid/relations/eager/base.rb +0 -153
  904. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  905. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  906. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  907. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  908. data/lib/mongoid/relations/embedded/in.rb +0 -241
  909. data/lib/mongoid/relations/embedded/many.rb +0 -683
  910. data/lib/mongoid/relations/embedded/one.rb +0 -235
  911. data/lib/mongoid/relations/macros.rb +0 -367
  912. data/lib/mongoid/relations/metadata.rb +0 -1179
  913. data/lib/mongoid/relations/nested_builder.rb +0 -74
  914. data/lib/mongoid/relations/options.rb +0 -49
  915. data/lib/mongoid/relations/polymorphic.rb +0 -39
  916. data/lib/mongoid/relations/referenced/in.rb +0 -304
  917. data/lib/mongoid/relations/referenced/many.rb +0 -812
  918. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
  919. data/lib/mongoid/relations/referenced/one.rb +0 -290
  920. data/lib/mongoid/relations/reflections.rb +0 -64
  921. data/lib/mongoid/relations/synchronization.rb +0 -169
  922. data/lib/mongoid/relations/targets/enumerable.rb +0 -493
  923. data/lib/mongoid/relations/targets.rb +0 -2
  924. data/lib/mongoid/relations/touchable.rb +0 -97
  925. data/lib/mongoid/relations.rb +0 -148
  926. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  927. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  928. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  929. data/spec/mongoid/relations/builders/embedded/in_spec.rb +0 -34
  930. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  931. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  932. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  933. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  934. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  935. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  936. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  937. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  938. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  939. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  940. data/spec/mongoid/relations/eager/belongs_to_spec.rb +0 -163
  941. data/spec/mongoid/relations/metadata_spec.rb +0 -1985
  942. data/spec/mongoid/relations/options_spec.rb +0 -35
@@ -1,43 +1,299 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
1
4
  require "spec_helper"
2
5
 
6
+ class FieldWithSerializer
7
+ def evolve(object)
8
+ Integer.evolve(object)
9
+ end
10
+
11
+ def localized?
12
+ false
13
+ end
14
+ end
15
+
3
16
  describe Mongoid::Criteria::Queryable::Selectable do
4
17
 
5
18
  let(:query) do
6
- Mongoid::Query.new("id" => "_id")
19
+ Mongoid::Query.new("id" => "_id")
7
20
  end
8
21
 
9
- shared_examples_for "a cloning selection" do
22
+ shared_examples_for "returns a cloned query" do
10
23
 
11
24
  it "returns a cloned query" do
12
25
  expect(selection).to_not equal(query)
13
26
  end
14
27
  end
15
28
 
16
- describe "#all" do
29
+ shared_examples_for 'requires an argument' do
30
+ context "when provided no argument" do
17
31
 
18
- context "when provided no criterion" do
32
+ let(:selection) do
33
+ query.send(query_method)
34
+ end
35
+
36
+ it "raises ArgumentError" do
37
+ expect do
38
+ selection.selector
39
+ end.to raise_error(ArgumentError)
40
+ end
41
+ end
42
+ end
43
+
44
+ shared_examples_for 'requires a non-nil argument' do
45
+ context "when provided nil" do
19
46
 
20
47
  let(:selection) do
21
- query.all
48
+ query.send(query_method, nil)
22
49
  end
23
50
 
24
- it "does not add any criterion" do
25
- expect(selection.selector).to eq({})
51
+ it "raises CriteriaArgumentRequired" do
52
+ expect do
53
+ selection.selector
54
+ end.to raise_error(Mongoid::Errors::CriteriaArgumentRequired, /#{query_method}/)
26
55
  end
56
+ end
57
+ end
27
58
 
28
- it "returns the query" do
29
- expect(selection).to eq(query)
59
+ shared_examples_for 'supports merge strategies' do
60
+
61
+ context 'when the field is not aliased' do
62
+
63
+ context "when the strategy is not set" do
64
+
65
+ let(:selection) do
66
+ query.send(query_method, first: [ 1, 2 ]).send(query_method, first: [ 3, 4 ])
67
+ end
68
+
69
+ it "combines the conditions with $and" do
70
+ expect(selection.selector).to eq({
71
+ "first" => { operator => [ 1, 2 ] },
72
+ '$and' => [{'first' => {operator => [3, 4]}}],
73
+ })
74
+ end
75
+
76
+ it_behaves_like "returns a cloned query"
30
77
  end
31
78
 
32
- it "returns a cloned query" do
33
- expect(selection).to_not equal(query)
79
+ context "when the strategy is intersect" do
80
+
81
+ let(:selection) do
82
+ query.send(query_method, first: [ 1, 2 ]).intersect.send(query_method, first: [ 2, 3 ])
83
+ end
84
+
85
+ it "intersects the conditions" do
86
+ expect(selection.selector).to eq({
87
+ "first" => { operator => [ 2 ] }
88
+ })
89
+ end
90
+
91
+ it_behaves_like "returns a cloned query"
92
+ end
93
+
94
+ context "when the strategy is override" do
95
+
96
+ let(:selection) do
97
+ query.send(query_method, first: [ 1, 2 ]).override.send(query_method, first: [ 3, 4 ])
98
+ end
99
+
100
+ it "overwrites the first condition" do
101
+ expect(selection.selector).to eq({
102
+ "first" => { operator => [ 3, 4 ] }
103
+ })
104
+ end
105
+
106
+ it_behaves_like "returns a cloned query"
107
+ end
108
+
109
+ context "when the strategy is union" do
110
+
111
+ let(:selection) do
112
+ query.send(query_method, first: [ 1, 2 ]).union.send(query_method, first: [ 3, 4 ])
113
+ end
114
+
115
+ it "unions the conditions" do
116
+ expect(selection.selector).to eq({
117
+ "first" => { operator => [ 1, 2, 3, 4 ] }
118
+ })
119
+ end
120
+
121
+ it_behaves_like "returns a cloned query"
34
122
  end
35
123
  end
36
124
 
37
- context "when provided nil" do
125
+ context 'when the field is aliased' do
126
+
127
+ context "when the strategy is not set" do
128
+
129
+ let(:selection) do
130
+ query.send(query_method, id: [ 1, 2 ]).send(query_method, _id: [ 3, 4 ])
131
+ end
132
+
133
+ it "combines the conditions with $and" do
134
+ expect(selection.selector).to eq({
135
+ "_id" => { operator => [ 1, 2 ] },
136
+ '$and' => [{'_id' => {operator => [3, 4]}}],
137
+ })
138
+ end
139
+
140
+ it_behaves_like "returns a cloned query"
141
+ end
142
+
143
+ context "when the strategy is intersect" do
144
+
145
+ let(:selection) do
146
+ query.send(query_method, id: [ 1, 2 ]).intersect.send(query_method, _id: [ 2, 3 ])
147
+ end
148
+
149
+ it "intersects the conditions" do
150
+ expect(selection.selector).to eq({
151
+ "_id" => { operator => [ 2 ] }
152
+ })
153
+ end
154
+
155
+ it_behaves_like "returns a cloned query"
156
+ end
157
+
158
+ context "when the strategy is override" do
159
+
160
+ let(:selection) do
161
+ query.send(query_method, _id: [ 1, 2 ]).override.send(query_method, id: [ 3, 4 ])
162
+ end
163
+
164
+ it "overwrites the first condition" do
165
+ expect(selection.selector).to eq({
166
+ "_id" => { operator => [ 3, 4 ] }
167
+ })
168
+ end
169
+
170
+ it_behaves_like "returns a cloned query"
171
+ end
172
+
173
+ context "when the strategy is union" do
174
+
175
+ let(:selection) do
176
+ query.send(query_method, _id: [ 1, 2 ]).union.send(query_method, id: [ 3, 4 ])
177
+ end
178
+
179
+ it "unions the conditions" do
180
+ expect(selection.selector).to eq({
181
+ "_id" => { operator => [ 1, 2, 3, 4 ] }
182
+ })
183
+ end
184
+
185
+ it_behaves_like "returns a cloned query"
186
+ end
187
+ end
188
+
189
+ context 'when the field uses a serializer' do
190
+
191
+ let(:query) do
192
+ Mongoid::Query.new({}, { "field" => FieldWithSerializer.new })
193
+ end
194
+
195
+
196
+ context "when the strategy is not set" do
197
+
198
+ let(:selection) do
199
+ query.send(query_method, field: [ '1', '2' ]).send(query_method, field: [ '3', '4' ])
200
+ end
201
+
202
+ it "combines the conditions with $and" do
203
+ expect(selection.selector).to eq({
204
+ "field" => { operator => [ 1, 2 ] },
205
+ '$and' => [{'field' => {operator => [3, 4]}}],
206
+ })
207
+ end
208
+
209
+ it_behaves_like "returns a cloned query"
210
+ end
211
+
212
+ context "when the strategy is set" do
213
+
214
+ let(:selection) do
215
+ query.send(query_method, field: [ '1', '2' ]).intersect.send(query_method, field: [ '2', '3' ])
216
+ end
217
+
218
+ it "intersects the conditions" do
219
+ expect(selection.selector).to eq({
220
+ "field" => { operator => [ 2 ] }
221
+ })
222
+ end
223
+
224
+ it_behaves_like "returns a cloned query"
225
+ end
226
+ end
227
+
228
+ context 'when operator value is a Range' do
229
+
230
+ context "when there is no existing condition and strategy is not specified" do
231
+
232
+ let(:selection) do
233
+ query.send(query_method, foo: 2..4)
234
+ end
235
+
236
+ it 'expands range to array' do
237
+ expect(selection.selector).to eq({
238
+ "foo" => { operator => [ 2, 3, 4 ] }
239
+ })
240
+
241
+ end
242
+ end
243
+
244
+ context "when there is no existing condition and strategy is specified" do
245
+
246
+ let(:selection) do
247
+ query.union.send(query_method, foo: 2..4)
248
+ end
249
+
250
+ it 'expands range to array' do
251
+ expect(selection.selector).to eq({
252
+ "foo" => { operator => [ 2, 3, 4 ] }
253
+ })
254
+
255
+ end
256
+ end
257
+
258
+ context "when existing condition has Array value" do
259
+
260
+ let(:selection) do
261
+ query.send(query_method, foo: [ 1, 2 ]).union.send(query_method, foo: 2..4)
262
+ end
263
+
264
+ it 'expands range to array' do
265
+ expect(selection.selector).to eq({
266
+ "foo" => { operator => [ 1, 2, 3, 4 ] }
267
+ })
268
+
269
+ end
270
+ end
271
+
272
+ context "when existing condition has Range value" do
273
+
274
+ let(:selection) do
275
+ query.send(query_method, foo: 1..2).union.send(query_method, foo: 2..4)
276
+ end
277
+
278
+ it 'expands range to array' do
279
+ expect(selection.selector).to eq({
280
+ "foo" => { operator => [ 1, 2, 3, 4 ] }
281
+ })
282
+
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ describe "#all" do
289
+
290
+ let(:query_method) { :all }
291
+ let(:operator) { '$all' }
292
+
293
+ context "when provided no criterion" do
38
294
 
39
295
  let(:selection) do
40
- query.all(nil)
296
+ query.all
41
297
  end
42
298
 
43
299
  it "does not add any criterion" do
@@ -53,6 +309,8 @@ describe Mongoid::Criteria::Queryable::Selectable do
53
309
  end
54
310
  end
55
311
 
312
+ it_behaves_like 'requires a non-nil argument'
313
+
56
314
  context "when provided a single criterion" do
57
315
 
58
316
  context "when no serializers are provided" do
@@ -74,23 +332,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
74
332
  end
75
333
  end
76
334
 
77
- context "when providing a range" do
78
-
79
- let(:selection) do
80
- query.all(field: 1..3)
81
- end
82
-
83
- it "adds the $all selector with converted range" do
84
- expect(selection.selector).to eq({
85
- "field" => { "$all" => [ 1, 2, 3 ] }
86
- })
87
- end
88
-
89
- it "returns a cloned query" do
90
- expect(selection).to_not equal(query)
91
- end
92
- end
93
-
94
335
  context "when providing a single value" do
95
336
 
96
337
  let(:selection) do
@@ -147,23 +388,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
147
388
  end
148
389
  end
149
390
 
150
- context "when providing a range" do
151
-
152
- let(:selection) do
153
- query.all(field: "1".."3")
154
- end
155
-
156
- it "adds the $all selector with converted range" do
157
- expect(selection.selector).to eq({
158
- "field" => { "$all" => [ 1, 2, 3 ] }
159
- })
160
- end
161
-
162
- it "returns a cloned query" do
163
- expect(selection).to_not equal(query)
164
- end
165
- end
166
-
167
391
  context "when providing a single value" do
168
392
 
169
393
  let(:selection) do
@@ -226,257 +450,120 @@ describe Mongoid::Criteria::Queryable::Selectable do
226
450
 
227
451
  context "when the criterion are on the same field" do
228
452
 
229
- context "when no serializers are provided" do
453
+ it_behaves_like 'supports merge strategies'
454
+ end
455
+ end
456
+ end
230
457
 
231
- context "when the strategy is the default (union)" do
458
+ describe "#between" do
232
459
 
233
- let(:selection) do
234
- query.all(first: [ 1, 2 ]).all(first: [ 3, 4 ])
235
- end
460
+ let(:query_method) { :between }
236
461
 
237
- it "overwrites the first $all selector" do
238
- expect(selection.selector).to eq({
239
- "first" => { "$all" => [ 1, 2, 3, 4 ] }
240
- })
241
- end
462
+ it_behaves_like 'requires an argument'
463
+ it_behaves_like 'requires a non-nil argument'
242
464
 
243
- it "returns a cloned query" do
244
- expect(selection).to_not equal(query)
245
- end
246
- end
465
+ context "when provided a single range" do
247
466
 
248
- context "when the strategy is intersect" do
467
+ let(:selection) do
468
+ query.between(field: 1..10)
469
+ end
249
470
 
250
- let(:selection) do
251
- query.all(first: [ 1, 2 ]).intersect.all(first: [ 2, 3 ])
252
- end
471
+ it "adds the $gte and $lte selectors" do
472
+ expect(selection.selector).to eq({
473
+ "field" => { "$gte" => 1, "$lte" => 10 }
474
+ })
475
+ end
253
476
 
254
- it "intersects the $all selectors" do
255
- expect(selection.selector).to eq({
256
- "first" => { "$all" => [ 2 ] }
257
- })
258
- end
477
+ it "returns a cloned query" do
478
+ expect(selection).to_not equal(query)
479
+ end
480
+ end
259
481
 
260
- it "returns a cloned query" do
261
- expect(selection).to_not equal(query)
262
- end
263
- end
482
+ context "when provided multiple ranges" do
264
483
 
265
- context "when the strategy is override" do
484
+ context "when the ranges are on different fields" do
266
485
 
267
- let(:selection) do
268
- query.all(first: [ 1, 2 ]).override.all(first: [ 3, 4 ])
269
- end
486
+ let(:selection) do
487
+ query.between(field: 1..10, key: 5..7)
488
+ end
270
489
 
271
- it "overwrites the first $all selector" do
272
- expect(selection.selector).to eq({
273
- "first" => { "$all" => [ 3, 4 ] }
274
- })
275
- end
490
+ it "adds the $gte and $lte selectors" do
491
+ expect(selection.selector).to eq({
492
+ "field" => { "$gte" => 1, "$lte" => 10 },
493
+ "key" => { "$gte" => 5, "$lte" => 7 }
494
+ })
495
+ end
276
496
 
277
- it "returns a cloned query" do
278
- expect(selection).to_not equal(query)
279
- end
280
- end
497
+ it "returns a cloned query" do
498
+ expect(selection).to_not equal(query)
499
+ end
500
+ end
501
+ end
502
+ end
281
503
 
282
- context "when the strategy is union" do
504
+ describe "#elem_match" do
283
505
 
284
- let(:selection) do
285
- query.all(first: [ 1, 2 ]).union.all(first: [ 3, 4 ])
286
- end
506
+ let(:query_method) { :elem_match }
287
507
 
288
- it "unions the $all selectors" do
289
- expect(selection.selector).to eq({
290
- "first" => { "$all" => [ 1, 2, 3, 4 ] }
291
- })
292
- end
508
+ it_behaves_like 'requires an argument'
509
+ it_behaves_like 'requires a non-nil argument'
293
510
 
294
- it "returns a cloned query" do
295
- expect(selection).to_not equal(query)
296
- end
297
- end
298
- end
299
-
300
- context "when serializers are provided" do
301
-
302
- before(:all) do
303
- class Field
304
- def evolve(object)
305
- Integer.evolve(object)
306
- end
307
- def localized?
308
- false
309
- end
310
- end
311
- end
312
-
313
- after(:all) do
314
- Object.send(:remove_const, :Field)
315
- end
316
-
317
- let!(:query) do
318
- Mongoid::Query.new({}, { "field" => Field.new })
319
- end
320
-
321
- context "when the strategy is the default (union)" do
322
-
323
- let(:selection) do
324
- query.all(field: [ "1", "2" ]).all(field: [ "3", "4" ])
325
- end
326
-
327
- it "overwrites the field $all selector" do
328
- expect(selection.selector).to eq({
329
- "field" => { "$all" => [ 1, 2, 3, 4 ] }
330
- })
331
- end
332
-
333
- it "returns a cloned query" do
334
- expect(selection).to_not equal(query)
335
- end
336
- end
337
-
338
- context "when the strategy is intersect" do
339
-
340
- let(:selection) do
341
- query.all(field: [ "1", "2" ]).intersect.all(field: [ "2", "3" ])
342
- end
343
-
344
- it "intersects the $all selectors" do
345
- expect(selection.selector).to eq({
346
- "field" => { "$all" => [ 2 ] }
347
- })
348
- end
349
-
350
- it "returns a cloned query" do
351
- expect(selection).to_not equal(query)
352
- end
353
- end
354
-
355
- context "when the strategy is override" do
356
-
357
- let(:selection) do
358
- query.all(field: [ "1", "2" ]).override.all(field: [ "3", "4" ])
359
- end
360
-
361
- it "overwrites the field $all selector" do
362
- expect(selection.selector).to eq({
363
- "field" => { "$all" => [ 3, 4 ] }
364
- })
365
- end
366
-
367
- it "returns a cloned query" do
368
- expect(selection).to_not equal(query)
369
- end
370
- end
371
-
372
- context "when the strategy is union" do
373
-
374
- let(:selection) do
375
- query.all(field: [ "1", "2" ]).union.all(field: [ "3", "4" ])
376
- end
511
+ context "when provided a criterion" do
377
512
 
378
- it "unions the $all selectors" do
379
- expect(selection.selector).to eq({
380
- "field" => { "$all" => [ 1, 2, 3, 4 ] }
381
- })
382
- end
513
+ context "when there are no nested complex keys" do
383
514
 
384
- it "returns a cloned query" do
385
- expect(selection).to_not equal(query)
386
- end
387
- end
515
+ let(:selection) do
516
+ query.elem_match(users: { name: "value" })
388
517
  end
389
- end
390
- end
391
- end
392
-
393
- describe "#and" do
394
-
395
- context "when provided no criterion" do
396
-
397
- let(:selection) do
398
- query.and
399
- end
400
-
401
- it "does not add any criterion" do
402
- expect(selection.selector).to eq({})
403
- end
404
-
405
- it "returns the query" do
406
- expect(selection).to eq(query)
407
- end
408
-
409
- it "returns a cloned query" do
410
- expect(selection).to_not equal(query)
411
- end
412
- end
413
-
414
- context "when provided nil" do
415
-
416
- let(:selection) do
417
- query.and(nil)
418
- end
419
-
420
- it "does not add any criterion" do
421
- expect(selection.selector).to eq({})
422
- end
423
-
424
- it "returns the query" do
425
- expect(selection).to eq(query)
426
- end
427
-
428
- it "returns a cloned query" do
429
- expect(selection).to_not equal(query)
430
- end
431
- end
432
518
 
433
- context "when provided a single criterion" do
434
-
435
- let(:selection) do
436
- query.and(field: [ 1, 2 ])
437
- end
519
+ it "adds the $elemMatch expression" do
520
+ expect(selection.selector).to eq({
521
+ "users" => { "$elemMatch" => { name: "value" }}
522
+ })
523
+ end
438
524
 
439
- it "adds the $and selector" do
440
- expect(selection.selector).to eq({
441
- "$and" => [{ "field" => [ 1, 2 ] }]
442
- })
525
+ it "returns a cloned query" do
526
+ expect(selection).to_not equal(query)
527
+ end
443
528
  end
444
529
 
445
- it "returns a cloned query" do
446
- expect(selection).to_not equal(query)
447
- end
448
- end
530
+ context "when there are nested complex keys" do
449
531
 
450
- context "when provided a nested criterion" do
532
+ let(:time) do
533
+ Time.now
534
+ end
451
535
 
452
- let(:selection) do
453
- query.and(:test.elem_match => { :field.in => [ 1, 2 ] })
454
- end
536
+ let(:selection) do
537
+ query.elem_match(users: { :time.gt => time })
538
+ end
455
539
 
456
- it "adds the $and selector" do
457
- expect(selection.selector).to eq({
458
- "$and" => [{ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}}]
459
- })
460
- end
540
+ it "adds the $elemMatch expression" do
541
+ expect(selection.selector).to eq({
542
+ "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
543
+ })
544
+ end
461
545
 
462
- it "returns a cloned query" do
463
- expect(selection).to_not equal(query)
546
+ it "returns a cloned query" do
547
+ expect(selection).to_not equal(query)
548
+ end
464
549
  end
465
550
  end
466
551
 
467
- context "when provided multiple criterion" do
552
+ context "when providing multiple criteria" do
468
553
 
469
- context "when the criterion is already included" do
554
+ context "when the fields differ" do
470
555
 
471
556
  let(:selection) do
472
- query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
557
+ query.elem_match(
558
+ users: { name: "value" },
559
+ comments: { text: "value" }
560
+ )
473
561
  end
474
562
 
475
- it "does not duplicate the $and selector" do
563
+ it "adds the $elemMatch expression" do
476
564
  expect(selection.selector).to eq({
477
- "$and" => [
478
- { "first" => [ 1, 2 ] }
479
- ]
565
+ "users" => { "$elemMatch" => { name: "value" }},
566
+ "comments" => { "$elemMatch" => { text: "value" }}
480
567
  })
481
568
  end
482
569
 
@@ -484,19 +571,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
484
571
  expect(selection).to_not equal(query)
485
572
  end
486
573
  end
574
+ end
487
575
 
488
- context "when the criterion are for different fields" do
576
+ context "when chaining multiple criteria" do
577
+
578
+ context "when the fields differ" do
489
579
 
490
580
  let(:selection) do
491
- query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
581
+ query.
582
+ elem_match(users: { name: "value" }).
583
+ elem_match(comments: { text: "value" })
492
584
  end
493
585
 
494
- it "adds the $and selector" do
586
+ it "adds the $elemMatch expression" do
495
587
  expect(selection.selector).to eq({
496
- "$and" => [
497
- { "first" => [ 1, 2 ] },
498
- { "second" => [ 3, 4 ] }
499
- ]
588
+ "users" => { "$elemMatch" => { name: "value" }},
589
+ "comments" => { "$elemMatch" => { text: "value" }}
500
590
  })
501
591
  end
502
592
 
@@ -505,18 +595,17 @@ describe Mongoid::Criteria::Queryable::Selectable do
505
595
  end
506
596
  end
507
597
 
508
- context "when the criterion are on the same field" do
598
+ context "when the fields are the same" do
509
599
 
510
600
  let(:selection) do
511
- query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
601
+ query.
602
+ elem_match(users: { name: "value" }).
603
+ elem_match(users: { state: "new" })
512
604
  end
513
605
 
514
- it "appends both $and expressions" do
606
+ it "overrides the $elemMatch expression" do
515
607
  expect(selection.selector).to eq({
516
- "$and" => [
517
- { "first" => [ 1, 2 ] },
518
- { "first" => [ 3, 4 ] }
519
- ]
608
+ "users" => { "$elemMatch" => { state: "new" }}
520
609
  })
521
610
  end
522
611
 
@@ -525,21 +614,26 @@ describe Mongoid::Criteria::Queryable::Selectable do
525
614
  end
526
615
  end
527
616
  end
617
+ end
528
618
 
529
- context "when chaining the criterion" do
619
+ describe "#exists" do
530
620
 
531
- context "when the criterion are for different fields" do
621
+ let(:query_method) { :exists }
622
+
623
+ it_behaves_like 'requires an argument'
624
+ it_behaves_like 'requires a non-nil argument'
625
+
626
+ context "when provided a criterion" do
627
+
628
+ context "when provided a boolean" do
532
629
 
533
630
  let(:selection) do
534
- query.and(first: [ 1, 2 ]).and(second: [ 3, 4 ])
631
+ query.exists(users: true)
535
632
  end
536
633
 
537
- it "adds the $and selectors" do
634
+ it "adds the $exists expression" do
538
635
  expect(selection.selector).to eq({
539
- "$and" => [
540
- { "first" => [ 1, 2 ] },
541
- { "second" => [ 3, 4 ] }
542
- ]
636
+ "users" => { "$exists" => true }
543
637
  })
544
638
  end
545
639
 
@@ -548,18 +642,15 @@ describe Mongoid::Criteria::Queryable::Selectable do
548
642
  end
549
643
  end
550
644
 
551
- context "when the criterion are on the same field" do
645
+ context "when provided a string" do
552
646
 
553
647
  let(:selection) do
554
- query.and(first: [ 1, 2 ]).and(first: [ 3, 4 ])
648
+ query.exists(users: "yes")
555
649
  end
556
650
 
557
- it "appends both $and expressions" do
651
+ it "adds the $exists expression" do
558
652
  expect(selection.selector).to eq({
559
- "$and" => [
560
- { "first" => [ 1, 2 ] },
561
- { "first" => [ 3, 4 ] }
562
- ]
653
+ "users" => { "$exists" => true }
563
654
  })
564
655
  end
565
656
 
@@ -568,1666 +659,218 @@ describe Mongoid::Criteria::Queryable::Selectable do
568
659
  end
569
660
  end
570
661
  end
571
- end
572
662
 
573
- describe "#between" do
663
+ context "when providing multiple criteria" do
574
664
 
575
- context "when provided no criterion" do
665
+ context "when the fields differ" do
576
666
 
577
- let(:selection) do
578
- query.between
579
- end
667
+ context "when providing boolean values" do
580
668
 
581
- it "does not add any criterion" do
582
- expect(selection.selector).to eq({})
583
- end
669
+ let(:selection) do
670
+ query.exists(
671
+ users: true,
672
+ comments: true
673
+ )
674
+ end
584
675
 
585
- it "returns the query" do
586
- expect(selection).to eq(query)
587
- end
676
+ it "adds the $exists expression" do
677
+ expect(selection.selector).to eq({
678
+ "users" => { "$exists" => true },
679
+ "comments" => { "$exists" => true }
680
+ })
681
+ end
588
682
 
589
- it "returns a cloned query" do
590
- expect(selection).to_not equal(query)
683
+ it "returns a cloned query" do
684
+ expect(selection).to_not equal(query)
685
+ end
686
+ end
687
+
688
+ context "when providing string values" do
689
+
690
+ let(:selection) do
691
+ query.exists(
692
+ users: "y",
693
+ comments: "true"
694
+ )
695
+ end
696
+
697
+ it "adds the $exists expression" do
698
+ expect(selection.selector).to eq({
699
+ "users" => { "$exists" => true },
700
+ "comments" => { "$exists" => true }
701
+ })
702
+ end
703
+
704
+ it "returns a cloned query" do
705
+ expect(selection).to_not equal(query)
706
+ end
707
+ end
591
708
  end
592
709
  end
593
710
 
594
- context "when provided nil" do
711
+ context "when chaining multiple criteria" do
595
712
 
596
- let(:selection) do
597
- query.between(nil)
598
- end
713
+ context "when the fields differ" do
599
714
 
600
- it "does not add any criterion" do
601
- expect(selection.selector).to eq({})
602
- end
715
+ let(:selection) do
716
+ query.
717
+ exists(users: true).
718
+ exists(comments: true)
719
+ end
603
720
 
604
- it "returns the query" do
605
- expect(selection).to eq(query)
606
- end
721
+ it "adds the $exists expression" do
722
+ expect(selection.selector).to eq({
723
+ "users" => { "$exists" => true },
724
+ "comments" => { "$exists" => true }
725
+ })
726
+ end
607
727
 
608
- it "returns a cloned query" do
609
- expect(selection).to_not equal(query)
728
+ it "returns a cloned query" do
729
+ expect(selection).to_not equal(query)
730
+ end
610
731
  end
611
732
  end
733
+ end
612
734
 
613
- context "when provided a single range" do
735
+ describe "#geo_spacial" do
614
736
 
615
- let(:selection) do
616
- query.between(field: 1..10)
617
- end
737
+ let(:query_method) { :geo_spacial }
618
738
 
619
- it "adds the $gte and $lte selectors" do
620
- expect(selection.selector).to eq({
621
- "field" => { "$gte" => 1, "$lte" => 10 }
622
- })
623
- end
624
-
625
- it "returns a cloned query" do
626
- expect(selection).to_not equal(query)
627
- end
628
- end
629
-
630
- context "when provided multiple ranges" do
631
-
632
- context "when the ranges are on different fields" do
633
-
634
- let(:selection) do
635
- query.between(field: 1..10, key: 5..7)
636
- end
637
-
638
- it "adds the $gte and $lte selectors" do
639
- expect(selection.selector).to eq({
640
- "field" => { "$gte" => 1, "$lte" => 10 },
641
- "key" => { "$gte" => 5, "$lte" => 7 }
642
- })
643
- end
644
-
645
- it "returns a cloned query" do
646
- expect(selection).to_not equal(query)
647
- end
648
- end
649
- end
650
- end
651
-
652
- describe "#elem_match" do
653
-
654
- context "when provided no criterion" do
655
-
656
- let(:selection) do
657
- query.elem_match
658
- end
659
-
660
- it "does not add any criterion" do
661
- expect(selection.selector).to eq({})
662
- end
663
-
664
- it "returns the query" do
665
- expect(selection).to eq(query)
666
- end
667
-
668
- it "returns a cloned query" do
669
- expect(selection).to_not equal(query)
670
- end
671
- end
672
-
673
- context "when provided nil" do
674
-
675
- let(:selection) do
676
- query.elem_match(nil)
677
- end
678
-
679
- it "does not add any criterion" do
680
- expect(selection.selector).to eq({})
681
- end
682
-
683
- it "returns the query" do
684
- expect(selection).to eq(query)
685
- end
686
-
687
- it "returns a cloned query" do
688
- expect(selection).to_not equal(query)
689
- end
690
- end
691
-
692
- context "when provided a criterion" do
693
-
694
- context "when there are no nested complex keys" do
695
-
696
- let(:selection) do
697
- query.elem_match(users: { name: "value" })
698
- end
699
-
700
- it "adds the $elemMatch expression" do
701
- expect(selection.selector).to eq({
702
- "users" => { "$elemMatch" => { name: "value" }}
703
- })
704
- end
705
-
706
- it "returns a cloned query" do
707
- expect(selection).to_not equal(query)
708
- end
709
- end
710
-
711
- context "when there are nested complex keys" do
712
-
713
- let(:time) do
714
- Time.now
715
- end
716
-
717
- let(:selection) do
718
- query.elem_match(users: { :time.gt => time })
719
- end
720
-
721
- it "adds the $elemMatch expression" do
722
- expect(selection.selector).to eq({
723
- "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
724
- })
725
- end
726
-
727
- it "returns a cloned query" do
728
- expect(selection).to_not equal(query)
729
- end
730
- end
731
- end
732
-
733
- context "when providing multiple criteria" do
734
-
735
- context "when the fields differ" do
736
-
737
- let(:selection) do
738
- query.elem_match(
739
- users: { name: "value" },
740
- comments: { text: "value" }
741
- )
742
- end
743
-
744
- it "adds the $elemMatch expression" do
745
- expect(selection.selector).to eq({
746
- "users" => { "$elemMatch" => { name: "value" }},
747
- "comments" => { "$elemMatch" => { text: "value" }}
748
- })
749
- end
750
-
751
- it "returns a cloned query" do
752
- expect(selection).to_not equal(query)
753
- end
754
- end
755
- end
756
-
757
- context "when chaining multiple criteria" do
758
-
759
- context "when the fields differ" do
760
-
761
- let(:selection) do
762
- query.
763
- elem_match(users: { name: "value" }).
764
- elem_match(comments: { text: "value" })
765
- end
766
-
767
- it "adds the $elemMatch expression" do
768
- expect(selection.selector).to eq({
769
- "users" => { "$elemMatch" => { name: "value" }},
770
- "comments" => { "$elemMatch" => { text: "value" }}
771
- })
772
- end
773
-
774
- it "returns a cloned query" do
775
- expect(selection).to_not equal(query)
776
- end
777
- end
778
-
779
- context "when the fields are the same" do
780
-
781
- let(:selection) do
782
- query.
783
- elem_match(users: { name: "value" }).
784
- elem_match(users: { state: "new" })
785
- end
786
-
787
- it "overrides the $elemMatch expression" do
788
- expect(selection.selector).to eq({
789
- "users" => { "$elemMatch" => { state: "new" }}
790
- })
791
- end
792
-
793
- it "returns a cloned query" do
794
- expect(selection).to_not equal(query)
795
- end
796
- end
797
- end
798
- end
799
-
800
- describe "#exists" do
801
-
802
- context "when provided no criterion" do
803
-
804
- let(:selection) do
805
- query.exists
806
- end
807
-
808
- it "does not add any criterion" do
809
- expect(selection.selector).to eq({})
810
- end
811
-
812
- it "returns the query" do
813
- expect(selection).to eq(query)
814
- end
815
-
816
- it "returns a cloned query" do
817
- expect(selection).to_not equal(query)
818
- end
819
- end
820
-
821
- context "when provided nil" do
822
-
823
- let(:selection) do
824
- query.exists(nil)
825
- end
826
-
827
- it "does not add any criterion" do
828
- expect(selection.selector).to eq({})
829
- end
830
-
831
- it "returns the query" do
832
- expect(selection).to eq(query)
833
- end
834
-
835
- it "returns a cloned query" do
836
- expect(selection).to_not equal(query)
837
- end
838
- end
839
-
840
- context "when provided a criterion" do
841
-
842
- context "when provided a boolean" do
843
-
844
- let(:selection) do
845
- query.exists(users: true)
846
- end
847
-
848
- it "adds the $exists expression" do
849
- expect(selection.selector).to eq({
850
- "users" => { "$exists" => true }
851
- })
852
- end
853
-
854
- it "returns a cloned query" do
855
- expect(selection).to_not equal(query)
856
- end
857
- end
858
-
859
- context "when provided a string" do
860
-
861
- let(:selection) do
862
- query.exists(users: "yes")
863
- end
864
-
865
- it "adds the $exists expression" do
866
- expect(selection.selector).to eq({
867
- "users" => { "$exists" => true }
868
- })
869
- end
870
-
871
- it "returns a cloned query" do
872
- expect(selection).to_not equal(query)
873
- end
874
- end
875
- end
876
-
877
- context "when providing multiple criteria" do
878
-
879
- context "when the fields differ" do
880
-
881
- context "when providing boolean values" do
882
-
883
- let(:selection) do
884
- query.exists(
885
- users: true,
886
- comments: true
887
- )
888
- end
889
-
890
- it "adds the $exists expression" do
891
- expect(selection.selector).to eq({
892
- "users" => { "$exists" => true },
893
- "comments" => { "$exists" => true }
894
- })
895
- end
896
-
897
- it "returns a cloned query" do
898
- expect(selection).to_not equal(query)
899
- end
900
- end
901
-
902
- context "when providing string values" do
903
-
904
- let(:selection) do
905
- query.exists(
906
- users: "y",
907
- comments: "true"
908
- )
909
- end
910
-
911
- it "adds the $exists expression" do
912
- expect(selection.selector).to eq({
913
- "users" => { "$exists" => true },
914
- "comments" => { "$exists" => true }
915
- })
916
- end
917
-
918
- it "returns a cloned query" do
919
- expect(selection).to_not equal(query)
920
- end
921
- end
922
- end
923
- end
924
-
925
- context "when chaining multiple criteria" do
926
-
927
- context "when the fields differ" do
928
-
929
- let(:selection) do
930
- query.
931
- exists(users: true).
932
- exists(comments: true)
933
- end
934
-
935
- it "adds the $exists expression" do
936
- expect(selection.selector).to eq({
937
- "users" => { "$exists" => true },
938
- "comments" => { "$exists" => true }
939
- })
940
- end
941
-
942
- it "returns a cloned query" do
943
- expect(selection).to_not equal(query)
944
- end
945
- end
946
- end
947
- end
948
-
949
- describe "#geo_spacial" do
950
-
951
- context "when provided no criterion" do
952
-
953
- let(:selection) do
954
- query.geo_spacial
955
- end
956
-
957
- it "does not add any criterion" do
958
- expect(selection.selector).to be_empty
959
- end
960
-
961
- it "returns the query" do
962
- expect(selection).to eq(query)
963
- end
964
-
965
- it_behaves_like "a cloning selection"
966
- end
967
-
968
- context "when provided nil" do
969
-
970
- let(:selection) do
971
- query.geo_spacial(nil)
972
- end
973
-
974
- it "does not add any criterion" do
975
- expect(selection.selector).to be_empty
976
- end
977
-
978
- it "returns the query" do
979
- expect(selection).to eq(query)
980
- end
981
-
982
- it_behaves_like "a cloning selection"
983
- end
984
-
985
- context "when provided a criterion" do
986
-
987
- context "when the geometry is a point intersection" do
988
-
989
- let(:selection) do
990
- query.geo_spacial(:location.intersects_point => [ 1, 10 ])
991
- end
992
-
993
- it "adds the $geoIntersects expression" do
994
- expect(selection.selector).to eq({
995
- "location" => {
996
- "$geoIntersects" => {
997
- "$geometry" => {
998
- "type" => "Point",
999
- "coordinates" => [ 1, 10 ]
1000
- }
1001
- }
1002
- }
1003
- })
1004
- end
1005
-
1006
- it_behaves_like "a cloning selection"
1007
- end
1008
-
1009
- context "when the geometry is a line intersection" do
1010
-
1011
- let(:selection) do
1012
- query.geo_spacial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
1013
- end
1014
-
1015
- it "adds the $geoIntersects expression" do
1016
- expect(selection.selector).to eq({
1017
- "location" => {
1018
- "$geoIntersects" => {
1019
- "$geometry" => {
1020
- "type" => "LineString",
1021
- "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
1022
- }
1023
- }
1024
- }
1025
- })
1026
- end
1027
-
1028
- it_behaves_like "a cloning selection"
1029
- end
1030
-
1031
- context "when the geometry is a polygon intersection" do
1032
-
1033
- let(:selection) do
1034
- query.geo_spacial(
1035
- :location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1036
- )
1037
- end
1038
-
1039
- it "adds the $geoIntersects expression" do
1040
- expect(selection.selector).to eq({
1041
- "location" => {
1042
- "$geoIntersects" => {
1043
- "$geometry" => {
1044
- "type" => "Polygon",
1045
- "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1046
- }
1047
- }
1048
- }
1049
- })
1050
- end
1051
-
1052
- it_behaves_like "a cloning selection"
1053
- end
1054
-
1055
- context "when the geometry is within a polygon" do
1056
-
1057
- let(:selection) do
1058
- query.geo_spacial(
1059
- :location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1060
- )
1061
- end
1062
-
1063
- it "adds the $geoIntersects expression" do
1064
- expect(selection.selector).to eq({
1065
- "location" => {
1066
- "$geoWithin" => {
1067
- "$geometry" => {
1068
- "type" => "Polygon",
1069
- "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1070
- }
1071
- }
1072
- }
1073
- })
1074
- end
1075
-
1076
- context "when used with the $box operator ($geoWithin query) " do
1077
- let(:selection) do
1078
- query.geo_spacial(
1079
- :location.within_box => [[ 1, 10 ], [ 2, 10 ]]
1080
- )
1081
- end
1082
-
1083
- it "adds the $geoIntersects expression" do
1084
- expect(selection.selector).to eq({
1085
- "location" => {
1086
- "$geoWithin" => {
1087
- "$box" => [
1088
- [ 1, 10 ], [ 2, 10 ]
1089
- ]
1090
- }
1091
- }
1092
- })
1093
- end
1094
- end
1095
-
1096
- it_behaves_like "a cloning selection"
1097
- end
1098
- end
1099
- end
1100
-
1101
- describe "#gt" do
1102
-
1103
- context "when provided no criterion" do
1104
-
1105
- let(:selection) do
1106
- query.gt
1107
- end
1108
-
1109
- it "does not add any criterion" do
1110
- expect(selection.selector).to eq({})
1111
- end
1112
-
1113
- it "returns the query" do
1114
- expect(selection).to eq(query)
1115
- end
1116
-
1117
- it "returns a cloned query" do
1118
- expect(selection).to_not equal(query)
1119
- end
1120
- end
1121
-
1122
- context "when provided nil" do
1123
-
1124
- let(:selection) do
1125
- query.gt(nil)
1126
- end
1127
-
1128
- it "does not add any criterion" do
1129
- expect(selection.selector).to eq({})
1130
- end
1131
-
1132
- it "returns the query" do
1133
- expect(selection).to eq(query)
1134
- end
1135
-
1136
- it "returns a cloned query" do
1137
- expect(selection).to_not equal(query)
1138
- end
1139
- end
1140
-
1141
- context "when provided a single criterion" do
1142
-
1143
- let(:selection) do
1144
- query.gt(field: 10)
1145
- end
1146
-
1147
- it "adds the $gt selector" do
1148
- expect(selection.selector).to eq({
1149
- "field" => { "$gt" => 10 }
1150
- })
1151
- end
1152
-
1153
- it "returns a cloned query" do
1154
- expect(selection).to_not equal(query)
1155
- end
1156
- end
1157
-
1158
- context "when provided multiple criterion" do
1159
-
1160
- context "when the criterion are for different fields" do
1161
-
1162
- let(:selection) do
1163
- query.gt(first: 10, second: 15)
1164
- end
1165
-
1166
- it "adds the $gt selectors" do
1167
- expect(selection.selector).to eq({
1168
- "first" => { "$gt" => 10 },
1169
- "second" => { "$gt" => 15 }
1170
- })
1171
- end
1172
-
1173
- it "returns a cloned query" do
1174
- expect(selection).to_not equal(query)
1175
- end
1176
- end
1177
- end
1178
-
1179
- context "when chaining the criterion" do
1180
-
1181
- context "when the criterion are for different fields" do
1182
-
1183
- let(:selection) do
1184
- query.gt(first: 10).gt(second: 15)
1185
- end
1186
-
1187
- it "adds the $gt selectors" do
1188
- expect(selection.selector).to eq({
1189
- "first" => { "$gt" => 10 },
1190
- "second" => { "$gt" => 15 }
1191
- })
1192
- end
1193
-
1194
- it "returns a cloned query" do
1195
- expect(selection).to_not equal(query)
1196
- end
1197
- end
1198
-
1199
- context "when the criterion are on the same field" do
1200
-
1201
- let(:selection) do
1202
- query.gt(first: 10).gt(first: 15)
1203
- end
1204
-
1205
- it "overwrites the first $gt selector" do
1206
- expect(selection.selector).to eq({
1207
- "first" => { "$gt" => 15 }
1208
- })
1209
- end
1210
-
1211
- it "returns a cloned query" do
1212
- expect(selection).to_not equal(query)
1213
- end
1214
- end
1215
- end
1216
- end
1217
-
1218
- describe "#gte" do
1219
-
1220
- context "when provided no criterion" do
1221
-
1222
- let(:selection) do
1223
- query.gte
1224
- end
1225
-
1226
- it "does not add any criterion" do
1227
- expect(selection.selector).to eq({})
1228
- end
1229
-
1230
- it "returns the query" do
1231
- expect(selection).to eq(query)
1232
- end
1233
-
1234
- it "returns a cloned query" do
1235
- expect(selection).to_not equal(query)
1236
- end
1237
- end
1238
-
1239
- context "when provided nil" do
1240
-
1241
- let(:selection) do
1242
- query.gte(nil)
1243
- end
1244
-
1245
- it "does not add any criterion" do
1246
- expect(selection.selector).to eq({})
1247
- end
1248
-
1249
- it "returns the query" do
1250
- expect(selection).to eq(query)
1251
- end
1252
-
1253
- it "returns a cloned query" do
1254
- expect(selection).to_not equal(query)
1255
- end
1256
- end
1257
-
1258
- context "when provided a single criterion" do
1259
-
1260
- let(:selection) do
1261
- query.gte(field: 10)
1262
- end
1263
-
1264
- it "adds the $gte selector" do
1265
- expect(selection.selector).to eq({
1266
- "field" => { "$gte" => 10 }
1267
- })
1268
- end
1269
-
1270
- it "returns a cloned query" do
1271
- expect(selection).to_not equal(query)
1272
- end
1273
- end
1274
-
1275
- context "when provided multiple criterion" do
1276
-
1277
- context "when the criterion are for different fields" do
1278
-
1279
- let(:selection) do
1280
- query.gte(first: 10, second: 15)
1281
- end
1282
-
1283
- it "adds the $gte selectors" do
1284
- expect(selection.selector).to eq({
1285
- "first" => { "$gte" => 10 },
1286
- "second" => { "$gte" => 15 }
1287
- })
1288
- end
1289
-
1290
- it "returns a cloned query" do
1291
- expect(selection).to_not equal(query)
1292
- end
1293
- end
1294
- end
1295
-
1296
- context "when chaining the criterion" do
1297
-
1298
- context "when the criterion are for different fields" do
1299
-
1300
- let(:selection) do
1301
- query.gte(first: 10).gte(second: 15)
1302
- end
1303
-
1304
- it "adds the $gte selectors" do
1305
- expect(selection.selector).to eq({
1306
- "first" => { "$gte" => 10 },
1307
- "second" => { "$gte" => 15 }
1308
- })
1309
- end
1310
-
1311
- it "returns a cloned query" do
1312
- expect(selection).to_not equal(query)
1313
- end
1314
- end
1315
-
1316
- context "when the criterion are on the same field" do
1317
-
1318
- let(:selection) do
1319
- query.gte(first: 10).gte(first: 15)
1320
- end
1321
-
1322
- it "overwrites the first $gte selector" do
1323
- expect(selection.selector).to eq({
1324
- "first" => { "$gte" => 15 }
1325
- })
1326
- end
1327
-
1328
- it "returns a cloned query" do
1329
- expect(selection).to_not equal(query)
1330
- end
1331
- end
1332
- end
1333
- end
1334
-
1335
- describe "#in" do
1336
-
1337
- context "when provided no criterion" do
1338
-
1339
- let(:selection) do
1340
- query.in
1341
- end
1342
-
1343
- it "does not add any criterion" do
1344
- expect(selection.selector).to eq({})
1345
- end
1346
-
1347
- it "returns the query" do
1348
- expect(selection).to eq(query)
1349
- end
1350
-
1351
- it "returns a cloned query" do
1352
- expect(selection).to_not equal(query)
1353
- end
1354
- end
1355
-
1356
- context "when provided nil" do
1357
-
1358
- let(:selection) do
1359
- query.in(nil)
1360
- end
1361
-
1362
- it "does not add any criterion" do
1363
- expect(selection.selector).to eq({})
1364
- end
1365
-
1366
- it "returns the query" do
1367
- expect(selection).to eq(query)
1368
- end
1369
-
1370
- it "returns a cloned query" do
1371
- expect(selection).to_not equal(query)
1372
- end
1373
- end
1374
-
1375
- context "when provided a single criterion" do
1376
-
1377
- context "when providing an array" do
1378
-
1379
- let(:selection) do
1380
- query.in(field: [ 1, 2 ])
1381
- end
1382
-
1383
- it "adds the $in selector" do
1384
- expect(selection.selector).to eq({
1385
- "field" => { "$in" => [ 1, 2 ] }
1386
- })
1387
- end
1388
-
1389
- it "returns a cloned query" do
1390
- expect(selection).to_not equal(query)
1391
- end
1392
- end
1393
-
1394
- context "when providing a range" do
1395
-
1396
- let(:selection) do
1397
- query.in(field: 1..3)
1398
- end
1399
-
1400
- it "adds the $in selector with converted range" do
1401
- expect(selection.selector).to eq({
1402
- "field" => { "$in" => [ 1, 2, 3 ] }
1403
- })
1404
- end
1405
-
1406
- it "returns a cloned query" do
1407
- expect(selection).to_not equal(query)
1408
- end
1409
- end
1410
-
1411
- context "when providing a single value" do
1412
-
1413
- let(:selection) do
1414
- query.in(field: 1)
1415
- end
1416
-
1417
- it "adds the $in selector with wrapped value" do
1418
- expect(selection.selector).to eq({
1419
- "field" => { "$in" => [ 1 ] }
1420
- })
1421
- end
1422
-
1423
- it "returns a cloned query" do
1424
- expect(selection).to_not equal(query)
1425
- end
1426
- end
1427
- end
1428
-
1429
- context "when provided multiple criterion" do
1430
-
1431
- context "when the criterion are for different fields" do
1432
-
1433
- let(:selection) do
1434
- query.in(first: [ 1, 2 ], second: 3..4)
1435
- end
1436
-
1437
- it "adds the $in selectors" do
1438
- expect(selection.selector).to eq({
1439
- "first" => { "$in" => [ 1, 2 ] },
1440
- "second" => { "$in" => [ 3, 4 ] }
1441
- })
1442
- end
1443
-
1444
- it "returns a cloned query" do
1445
- expect(selection).to_not equal(query)
1446
- end
1447
- end
1448
- end
1449
-
1450
- context "when chaining the criterion" do
1451
-
1452
- context "when the criterion are for different fields" do
1453
-
1454
- let(:selection) do
1455
- query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
1456
- end
1457
-
1458
- it "adds the $in selectors" do
1459
- expect(selection.selector).to eq({
1460
- "first" => { "$in" => [ 1, 2 ] },
1461
- "second" => { "$in" => [ 3, 4 ] }
1462
- })
1463
- end
1464
-
1465
- it "returns a cloned query" do
1466
- expect(selection).to_not equal(query)
1467
- end
1468
- end
1469
-
1470
- context "when the criterion are on the same field" do
1471
-
1472
- context "when the strategy is the default (intersection)" do
1473
-
1474
- let(:selection) do
1475
- query.in(first: [ 1, 2 ].freeze).in(first: [ 2, 3 ])
1476
- end
1477
-
1478
- it "intersects the $in selectors" do
1479
- expect(selection.selector).to eq({
1480
- "first" => { "$in" => [ 2 ] }
1481
- })
1482
- end
1483
-
1484
- it "returns a cloned query" do
1485
- expect(selection).to_not equal(query)
1486
- end
1487
- end
1488
-
1489
- context 'when the field is aliased' do
1490
-
1491
- before(:all) do
1492
- class TestModel
1493
- include Mongoid::Document
1494
- end
1495
- end
1496
-
1497
- after(:all) do
1498
- Object.send(:remove_const, :TestModel)
1499
- end
1500
-
1501
- let(:bson_object_id) do
1502
- BSON::ObjectId.new
1503
- end
1504
-
1505
- let(:selection) do
1506
- TestModel.in(id: [bson_object_id.to_s]).in(id: [bson_object_id.to_s])
1507
- end
1508
-
1509
- it "intersects the $in selectors" do
1510
- expect(selection.selector).to eq("_id" => { "$in" => [ bson_object_id ] })
1511
- end
1512
-
1513
- it "returns a cloned query" do
1514
- expect(selection).to_not equal(query)
1515
- end
1516
- end
1517
-
1518
- context "when the stretegy is intersect" do
1519
-
1520
- let(:selection) do
1521
- query.in(first: [ 1, 2 ]).intersect.in(first: [ 2, 3 ])
1522
- end
1523
-
1524
- it "intersects the $in selectors" do
1525
- expect(selection.selector).to eq({
1526
- "first" => { "$in" => [ 2 ] }
1527
- })
1528
- end
1529
-
1530
- it "returns a cloned query" do
1531
- expect(selection).to_not equal(query)
1532
- end
1533
- end
1534
-
1535
- context "when the strategy is override" do
1536
-
1537
- let(:selection) do
1538
- query.in(first: [ 1, 2 ]).override.in(first: [ 3, 4 ])
1539
- end
1540
-
1541
- it "overwrites the first $in selector" do
1542
- expect(selection.selector).to eq({
1543
- "first" => { "$in" => [ 3, 4 ] }
1544
- })
1545
- end
1546
-
1547
- it "returns a cloned query" do
1548
- expect(selection).to_not equal(query)
1549
- end
1550
- end
1551
-
1552
- context "when the strategy is union" do
1553
-
1554
- let(:selection) do
1555
- query.in(first: [ 1, 2 ]).union.in(first: [ 3, 4 ])
1556
- end
1557
-
1558
- it "unions the $in selectors" do
1559
- expect(selection.selector).to eq({
1560
- "first" => { "$in" => [ 1, 2, 3, 4 ] }
1561
- })
1562
- end
1563
-
1564
- it "returns a cloned query" do
1565
- expect(selection).to_not equal(query)
1566
- end
1567
- end
1568
- end
1569
- end
1570
- end
1571
-
1572
- describe "#lt" do
1573
-
1574
- context "when provided no criterion" do
1575
-
1576
- let(:selection) do
1577
- query.lt
1578
- end
1579
-
1580
- it "does not add any criterion" do
1581
- expect(selection.selector).to eq({})
1582
- end
1583
-
1584
- it "returns the query" do
1585
- expect(selection).to eq(query)
1586
- end
1587
-
1588
- it "returns a cloned query" do
1589
- expect(selection).to_not equal(query)
1590
- end
1591
- end
1592
-
1593
- context "when provided nil" do
1594
-
1595
- let(:selection) do
1596
- query.lt(nil)
1597
- end
1598
-
1599
- it "does not add any criterion" do
1600
- expect(selection.selector).to eq({})
1601
- end
1602
-
1603
- it "returns the query" do
1604
- expect(selection).to eq(query)
1605
- end
1606
-
1607
- it "returns a cloned query" do
1608
- expect(selection).to_not equal(query)
1609
- end
1610
- end
1611
-
1612
- context "when provided a single criterion" do
1613
-
1614
- let(:selection) do
1615
- query.lt(field: 10)
1616
- end
1617
-
1618
- it "adds the $lt selector" do
1619
- expect(selection.selector).to eq({
1620
- "field" => { "$lt" => 10 }
1621
- })
1622
- end
1623
-
1624
- it "returns a cloned query" do
1625
- expect(selection).to_not equal(query)
1626
- end
1627
- end
1628
-
1629
- context "when provided multiple criterion" do
1630
-
1631
- context "when the criterion are for different fields" do
1632
-
1633
- let(:selection) do
1634
- query.lt(first: 10, second: 15)
1635
- end
1636
-
1637
- it "adds the $lt selectors" do
1638
- expect(selection.selector).to eq({
1639
- "first" => { "$lt" => 10 },
1640
- "second" => { "$lt" => 15 }
1641
- })
1642
- end
1643
-
1644
- it "returns a cloned query" do
1645
- expect(selection).to_not equal(query)
1646
- end
1647
- end
1648
- end
1649
-
1650
- context "when chaining the criterion" do
1651
-
1652
- context "when the criterion are for different fields" do
1653
-
1654
- let(:selection) do
1655
- query.lt(first: 10).lt(second: 15)
1656
- end
1657
-
1658
- it "adds the $lt selectors" do
1659
- expect(selection.selector).to eq({
1660
- "first" => { "$lt" => 10 },
1661
- "second" => { "$lt" => 15 }
1662
- })
1663
- end
1664
-
1665
- it "returns a cloned query" do
1666
- expect(selection).to_not equal(query)
1667
- end
1668
- end
1669
-
1670
- context "when the criterion are on the same field" do
1671
-
1672
- let(:selection) do
1673
- query.lt(first: 10).lt(first: 15)
1674
- end
1675
-
1676
- it "overwrites the first $lt selector" do
1677
- expect(selection.selector).to eq({
1678
- "first" => { "$lt" => 15 }
1679
- })
1680
- end
1681
-
1682
- it "returns a cloned query" do
1683
- expect(selection).to_not equal(query)
1684
- end
1685
- end
1686
- end
1687
- end
1688
-
1689
- describe "#lte" do
1690
-
1691
- context "when provided no criterion" do
1692
-
1693
- let(:selection) do
1694
- query.lte
1695
- end
1696
-
1697
- it "does not add any criterion" do
1698
- expect(selection.selector).to eq({})
1699
- end
1700
-
1701
- it "returns the query" do
1702
- expect(selection).to eq(query)
1703
- end
1704
-
1705
- it "returns a cloned query" do
1706
- expect(selection).to_not equal(query)
1707
- end
1708
- end
1709
-
1710
- context "when provided nil" do
1711
-
1712
- let(:selection) do
1713
- query.lte(nil)
1714
- end
1715
-
1716
- it "does not add any criterion" do
1717
- expect(selection.selector).to eq({})
1718
- end
1719
-
1720
- it "returns the query" do
1721
- expect(selection).to eq(query)
1722
- end
1723
-
1724
- it "returns a cloned query" do
1725
- expect(selection).to_not equal(query)
1726
- end
1727
- end
1728
-
1729
- context "when provided a single criterion" do
1730
-
1731
- let(:selection) do
1732
- query.lte(field: 10)
1733
- end
1734
-
1735
- it "adds the $lte selector" do
1736
- expect(selection.selector).to eq({
1737
- "field" => { "$lte" => 10 }
1738
- })
1739
- end
1740
-
1741
- it "returns a cloned query" do
1742
- expect(selection).to_not equal(query)
1743
- end
1744
- end
1745
-
1746
- context "when provided multiple criterion" do
1747
-
1748
- context "when the criterion are for different fields" do
1749
-
1750
- let(:selection) do
1751
- query.lte(first: 10, second: 15)
1752
- end
1753
-
1754
- it "adds the $lte selectors" do
1755
- expect(selection.selector).to eq({
1756
- "first" => { "$lte" => 10 },
1757
- "second" => { "$lte" => 15 }
1758
- })
1759
- end
1760
-
1761
- it "returns a cloned query" do
1762
- expect(selection).to_not equal(query)
1763
- end
1764
- end
1765
- end
1766
-
1767
- context "when chaining the criterion" do
1768
-
1769
- context "when the criterion are for different fields" do
1770
-
1771
- let(:selection) do
1772
- query.lte(first: 10).lte(second: 15)
1773
- end
1774
-
1775
- it "adds the $lte selectors" do
1776
- expect(selection.selector).to eq({
1777
- "first" => { "$lte" => 10 },
1778
- "second" => { "$lte" => 15 }
1779
- })
1780
- end
1781
-
1782
- it "returns a cloned query" do
1783
- expect(selection).to_not equal(query)
1784
- end
1785
- end
1786
-
1787
- context "when the criterion are on the same field" do
1788
-
1789
- let(:selection) do
1790
- query.lte(first: 10).lte(first: 15)
1791
- end
1792
-
1793
- it "overwrites the first $lte selector" do
1794
- expect(selection.selector).to eq({
1795
- "first" => { "$lte" => 15 }
1796
- })
1797
- end
1798
-
1799
- it "returns a cloned query" do
1800
- expect(selection).to_not equal(query)
1801
- end
1802
- end
1803
- end
1804
- end
1805
-
1806
- describe "#max_distance" do
1807
-
1808
- context "when provided no criterion" do
1809
-
1810
- let(:selection) do
1811
- query.max_distance
1812
- end
1813
-
1814
- it "does not add any criterion" do
1815
- expect(selection.selector).to eq({})
1816
- end
1817
-
1818
- it "returns the query" do
1819
- expect(selection).to eq(query)
1820
- end
1821
-
1822
- it "returns a cloned query" do
1823
- expect(selection).to_not equal(query)
1824
- end
1825
- end
1826
-
1827
- context "when provided nil" do
1828
-
1829
- let(:selection) do
1830
- query.max_distance(nil)
1831
- end
1832
-
1833
- it "does not add any criterion" do
1834
- expect(selection.selector).to eq({})
1835
- end
1836
-
1837
- it "returns the query" do
1838
- expect(selection).to eq(query)
1839
- end
1840
-
1841
- it "returns a cloned query" do
1842
- expect(selection).to_not equal(query)
1843
- end
1844
- end
1845
-
1846
- context "when provided a criterion" do
1847
-
1848
- context "when a $near criterion exists on the same field" do
1849
-
1850
- let(:selection) do
1851
- query.near(location: [ 1, 1 ]).max_distance(location: 50)
1852
- end
1853
-
1854
- it "adds the $maxDistance expression" do
1855
- expect(selection.selector).to eq({
1856
- "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
1857
- })
1858
- end
1859
-
1860
- it "returns a cloned query" do
1861
- expect(selection).to_not equal(query)
1862
- end
1863
- end
1864
- end
1865
- end
1866
-
1867
- describe "#mod" do
1868
-
1869
- context "when provided no criterion" do
1870
-
1871
- let(:selection) do
1872
- query.mod
1873
- end
1874
-
1875
- it "does not add any criterion" do
1876
- expect(selection.selector).to eq({})
1877
- end
1878
-
1879
- it "returns the query" do
1880
- expect(selection).to eq(query)
1881
- end
1882
-
1883
- it "returns a cloned query" do
1884
- expect(selection).to_not equal(query)
1885
- end
1886
- end
1887
-
1888
- context "when provided nil" do
1889
-
1890
- let(:selection) do
1891
- query.mod(nil)
1892
- end
1893
-
1894
- it "does not add any criterion" do
1895
- expect(selection.selector).to eq({})
1896
- end
1897
-
1898
- it "returns the query" do
1899
- expect(selection).to eq(query)
1900
- end
1901
-
1902
- it "returns a cloned query" do
1903
- expect(selection).to_not equal(query)
1904
- end
1905
- end
1906
-
1907
- context "when provided a criterion" do
1908
-
1909
- let(:selection) do
1910
- query.mod(value: [ 10, 1 ])
1911
- end
1912
-
1913
- it "adds the $mod expression" do
1914
- expect(selection.selector).to eq({
1915
- "value" => { "$mod" => [ 10, 1 ] }
1916
- })
1917
- end
1918
-
1919
- it "returns a cloned query" do
1920
- expect(selection).to_not equal(query)
1921
- end
1922
- end
1923
-
1924
- context "when providing multiple criteria" do
1925
-
1926
- context "when the fields differ" do
1927
-
1928
- let(:selection) do
1929
- query.mod(
1930
- value: [ 10, 1 ],
1931
- comments: [ 10, 1 ]
1932
- )
1933
- end
1934
-
1935
- it "adds the $mod expression" do
1936
- expect(selection.selector).to eq({
1937
- "value" => { "$mod" => [ 10, 1 ] },
1938
- "comments" => { "$mod" => [ 10, 1 ] }
1939
- })
1940
- end
1941
-
1942
- it "returns a cloned query" do
1943
- expect(selection).to_not equal(query)
1944
- end
1945
- end
1946
- end
1947
-
1948
- context "when chaining multiple criteria" do
1949
-
1950
- context "when the fields differ" do
1951
-
1952
- let(:selection) do
1953
- query.
1954
- mod(value: [ 10, 1 ]).
1955
- mod(result: [ 10, 1 ])
1956
- end
1957
-
1958
- it "adds the $mod expression" do
1959
- expect(selection.selector).to eq({
1960
- "value" => { "$mod" => [ 10, 1 ] },
1961
- "result" => { "$mod" => [ 10, 1 ] }
1962
- })
1963
- end
1964
-
1965
- it "returns a cloned query" do
1966
- expect(selection).to_not equal(query)
1967
- end
1968
- end
1969
- end
1970
- end
1971
-
1972
- describe "#ne" do
1973
-
1974
- context "when provided no criterion" do
1975
-
1976
- let(:selection) do
1977
- query.ne
1978
- end
1979
-
1980
- it "does not add any criterion" do
1981
- expect(selection.selector).to eq({})
1982
- end
1983
-
1984
- it "returns the query" do
1985
- expect(selection).to eq(query)
1986
- end
1987
-
1988
- it "returns a cloned query" do
1989
- expect(selection).to_not equal(query)
1990
- end
1991
- end
1992
-
1993
- context "when provided nil" do
1994
-
1995
- let(:selection) do
1996
- query.ne(nil)
1997
- end
1998
-
1999
- it "does not add any criterion" do
2000
- expect(selection.selector).to eq({})
2001
- end
2002
-
2003
- it "returns the query" do
2004
- expect(selection).to eq(query)
2005
- end
2006
-
2007
- it "returns a cloned query" do
2008
- expect(selection).to_not equal(query)
2009
- end
2010
- end
739
+ it_behaves_like 'requires an argument'
740
+ it_behaves_like 'requires a non-nil argument'
2011
741
 
2012
742
  context "when provided a criterion" do
2013
743
 
2014
- let(:selection) do
2015
- query.ne(value: 10)
2016
- end
2017
-
2018
- it "adds the $ne expression" do
2019
- expect(selection.selector).to eq({
2020
- "value" => { "$ne" => 10 }
2021
- })
2022
- end
2023
-
2024
- it "returns a cloned query" do
2025
- expect(selection).to_not equal(query)
2026
- end
2027
- end
2028
-
2029
- context "when providing multiple criteria" do
2030
-
2031
- context "when the fields differ" do
744
+ context "when the geometry is a point intersection" do
2032
745
 
2033
746
  let(:selection) do
2034
- query.ne(
2035
- value: 10,
2036
- comments: 10
2037
- )
747
+ query.geo_spacial(:location.intersects_point => [ 1, 10 ])
2038
748
  end
2039
749
 
2040
- it "adds the $ne expression" do
750
+ it "adds the $geoIntersects expression" do
2041
751
  expect(selection.selector).to eq({
2042
- "value" => { "$ne" => 10 },
2043
- "comments" => { "$ne" => 10 }
752
+ "location" => {
753
+ "$geoIntersects" => {
754
+ "$geometry" => {
755
+ "type" => "Point",
756
+ "coordinates" => [ 1, 10 ]
757
+ }
758
+ }
759
+ }
2044
760
  })
2045
761
  end
2046
762
 
2047
- it "returns a cloned query" do
2048
- expect(selection).to_not equal(query)
2049
- end
763
+ it_behaves_like "returns a cloned query"
2050
764
  end
2051
- end
2052
765
 
2053
- context "when chaining multiple criteria" do
2054
-
2055
- context "when the fields differ" do
766
+ context "when the geometry is a line intersection" do
2056
767
 
2057
768
  let(:selection) do
2058
- query.
2059
- ne(value: 10).
2060
- ne(result: 10)
769
+ query.geo_spacial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
2061
770
  end
2062
771
 
2063
- it "adds the $ne expression" do
772
+ it "adds the $geoIntersects expression" do
2064
773
  expect(selection.selector).to eq({
2065
- "value" => { "$ne" => 10 },
2066
- "result" => { "$ne" => 10 }
774
+ "location" => {
775
+ "$geoIntersects" => {
776
+ "$geometry" => {
777
+ "type" => "LineString",
778
+ "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
779
+ }
780
+ }
781
+ }
2067
782
  })
2068
783
  end
2069
784
 
2070
- it "returns a cloned query" do
2071
- expect(selection).to_not equal(query)
2072
- end
2073
- end
2074
- end
2075
- end
2076
-
2077
- describe "#near" do
2078
-
2079
- context "when provided no criterion" do
2080
-
2081
- let(:selection) do
2082
- query.near
2083
- end
2084
-
2085
- it "does not add any criterion" do
2086
- expect(selection.selector).to eq({})
2087
- end
2088
-
2089
- it "returns the query" do
2090
- expect(selection).to eq(query)
2091
- end
2092
-
2093
- it "returns a cloned query" do
2094
- expect(selection).to_not equal(query)
2095
- end
2096
- end
2097
-
2098
- context "when provided nil" do
2099
-
2100
- let(:selection) do
2101
- query.near(nil)
2102
- end
2103
-
2104
- it "does not add any criterion" do
2105
- expect(selection.selector).to eq({})
2106
- end
2107
-
2108
- it "returns the query" do
2109
- expect(selection).to eq(query)
2110
- end
2111
-
2112
- it "returns a cloned query" do
2113
- expect(selection).to_not equal(query)
2114
- end
2115
- end
2116
-
2117
- context "when provided a criterion" do
2118
-
2119
- let(:selection) do
2120
- query.near(location: [ 20, 21 ])
2121
- end
2122
-
2123
- it "adds the $near expression" do
2124
- expect(selection.selector).to eq({
2125
- "location" => { "$near" => [ 20, 21 ] }
2126
- })
2127
- end
2128
-
2129
- it "returns a cloned query" do
2130
- expect(selection).to_not equal(query)
785
+ it_behaves_like "returns a cloned query"
2131
786
  end
2132
- end
2133
787
 
2134
- context "when providing multiple criteria" do
2135
-
2136
- context "when the fields differ" do
788
+ context "when the geometry is a polygon intersection" do
2137
789
 
2138
790
  let(:selection) do
2139
- query.near(
2140
- location: [ 20, 21 ],
2141
- comments: [ 20, 21 ]
791
+ query.geo_spacial(
792
+ :location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
2142
793
  )
2143
794
  end
2144
795
 
2145
- it "adds the $near expression" do
796
+ it "adds the $geoIntersects expression" do
2146
797
  expect(selection.selector).to eq({
2147
- "location" => { "$near" => [ 20, 21 ] },
2148
- "comments" => { "$near" => [ 20, 21 ] }
798
+ "location" => {
799
+ "$geoIntersects" => {
800
+ "$geometry" => {
801
+ "type" => "Polygon",
802
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
803
+ }
804
+ }
805
+ }
2149
806
  })
2150
807
  end
2151
808
 
2152
- it "returns a cloned query" do
2153
- expect(selection).to_not equal(query)
2154
- end
809
+ it_behaves_like "returns a cloned query"
2155
810
  end
2156
- end
2157
-
2158
- context "when chaining multiple criteria" do
2159
811
 
2160
- context "when the fields differ" do
812
+ context "when the geometry is within a polygon" do
2161
813
 
2162
814
  let(:selection) do
2163
- query.
2164
- near(location: [ 20, 21 ]).
2165
- near(comments: [ 20, 21 ])
815
+ query.geo_spacial(
816
+ :location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
817
+ )
2166
818
  end
2167
819
 
2168
- it "adds the $near expression" do
820
+ it "adds the $geoIntersects expression" do
2169
821
  expect(selection.selector).to eq({
2170
- "location" => { "$near" => [ 20, 21 ] },
2171
- "comments" => { "$near" => [ 20, 21 ] }
822
+ "location" => {
823
+ "$geoWithin" => {
824
+ "$geometry" => {
825
+ "type" => "Polygon",
826
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
827
+ }
828
+ }
829
+ }
2172
830
  })
2173
831
  end
2174
832
 
2175
- it "returns a cloned query" do
2176
- expect(selection).to_not equal(query)
2177
- end
2178
- end
2179
- end
2180
- end
2181
-
2182
- describe "#near_sphere" do
2183
-
2184
- context "when provided no criterion" do
2185
-
2186
- let(:selection) do
2187
- query.near_sphere
2188
- end
2189
-
2190
- it "does not add any criterion" do
2191
- expect(selection.selector).to eq({})
2192
- end
2193
-
2194
- it "returns the query" do
2195
- expect(selection).to eq(query)
2196
- end
2197
-
2198
- it "returns a cloned query" do
2199
- expect(selection).to_not equal(query)
2200
- end
2201
- end
833
+ context "when used with the $box operator ($geoWithin query) " do
834
+ let(:selection) do
835
+ query.geo_spacial(
836
+ :location.within_box => [[ 1, 10 ], [ 2, 10 ]]
837
+ )
838
+ end
2202
839
 
2203
- context "when provided nil" do
840
+ it "adds the $geoIntersects expression" do
841
+ expect(selection.selector).to eq({
842
+ "location" => {
843
+ "$geoWithin" => {
844
+ "$box" => [
845
+ [ 1, 10 ], [ 2, 10 ]
846
+ ]
847
+ }
848
+ }
849
+ })
850
+ end
851
+ end
2204
852
 
2205
- let(:selection) do
2206
- query.near_sphere(nil)
853
+ it_behaves_like "returns a cloned query"
2207
854
  end
855
+ end
856
+ end
2208
857
 
2209
- it "does not add any criterion" do
2210
- expect(selection.selector).to eq({})
2211
- end
858
+ describe "#gt" do
2212
859
 
2213
- it "returns the query" do
2214
- expect(selection).to eq(query)
2215
- end
860
+ let(:query_method) { :gt }
2216
861
 
2217
- it "returns a cloned query" do
2218
- expect(selection).to_not equal(query)
2219
- end
2220
- end
862
+ it_behaves_like 'requires an argument'
863
+ it_behaves_like 'requires a non-nil argument'
2221
864
 
2222
- context "when provided a criterion" do
865
+ context "when provided a single criterion" do
2223
866
 
2224
867
  let(:selection) do
2225
- query.near_sphere(location: [ 20, 21 ])
868
+ query.gt(field: 10)
2226
869
  end
2227
870
 
2228
- it "adds the $nearSphere expression" do
871
+ it "adds the $gt selector" do
2229
872
  expect(selection.selector).to eq({
2230
- "location" => { "$nearSphere" => [ 20, 21 ] }
873
+ "field" => { "$gt" => 10 }
2231
874
  })
2232
875
  end
2233
876
 
@@ -2236,21 +879,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
2236
879
  end
2237
880
  end
2238
881
 
2239
- context "when providing multiple criteria" do
882
+ context "when provided multiple criterion" do
2240
883
 
2241
- context "when the fields differ" do
884
+ context "when the criterion are for different fields" do
2242
885
 
2243
886
  let(:selection) do
2244
- query.near_sphere(
2245
- location: [ 20, 21 ],
2246
- comments: [ 20, 21 ]
2247
- )
887
+ query.gt(first: 10, second: 15)
2248
888
  end
2249
889
 
2250
- it "adds the $nearSphere expression" do
890
+ it "adds the $gt selectors" do
2251
891
  expect(selection.selector).to eq({
2252
- "location" => { "$nearSphere" => [ 20, 21 ] },
2253
- "comments" => { "$nearSphere" => [ 20, 21 ] }
892
+ "first" => { "$gt" => 10 },
893
+ "second" => { "$gt" => 15 }
2254
894
  })
2255
895
  end
2256
896
 
@@ -2260,20 +900,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
2260
900
  end
2261
901
  end
2262
902
 
2263
- context "when chaining multiple criteria" do
903
+ context "when chaining the criterion" do
2264
904
 
2265
- context "when the fields differ" do
905
+ context "when the criterion are for different fields" do
2266
906
 
2267
907
  let(:selection) do
2268
- query.
2269
- near_sphere(location: [ 20, 21 ]).
2270
- near_sphere(comments: [ 20, 21 ])
908
+ query.gt(first: 10).gt(second: 15)
2271
909
  end
2272
910
 
2273
- it "adds the $nearSphere expression" do
911
+ it "adds the $gt selectors" do
2274
912
  expect(selection.selector).to eq({
2275
- "location" => { "$nearSphere" => [ 20, 21 ] },
2276
- "comments" => { "$nearSphere" => [ 20, 21 ] }
913
+ "first" => { "$gt" => 10 },
914
+ "second" => { "$gt" => 15 }
2277
915
  })
2278
916
  end
2279
917
 
@@ -2281,42 +919,43 @@ describe Mongoid::Criteria::Queryable::Selectable do
2281
919
  expect(selection).to_not equal(query)
2282
920
  end
2283
921
  end
2284
- end
2285
- end
2286
922
 
2287
- describe "#nin" do
923
+ context "when the criterion are on the same field" do
2288
924
 
2289
- context "when provided no criterion" do
925
+ let(:selection) do
926
+ query.gt(first: 10).gt(first: 15)
927
+ end
2290
928
 
2291
- let(:selection) do
2292
- query.nin
2293
- end
929
+ it "overwrites the first $gt selector" do
930
+ expect(selection.selector).to eq({
931
+ "first" => { "$gt" => 15 }
932
+ })
933
+ end
2294
934
 
2295
- it "does not add any criterion" do
2296
- expect(selection.selector).to eq({})
935
+ it "returns a cloned query" do
936
+ expect(selection).to_not equal(query)
937
+ end
2297
938
  end
939
+ end
940
+ end
2298
941
 
2299
- it "returns the query" do
2300
- expect(selection).to eq(query)
2301
- end
942
+ describe "#gte" do
2302
943
 
2303
- it "returns a cloned query" do
2304
- expect(selection).to_not equal(query)
2305
- end
2306
- end
944
+ let(:query_method) { :gte }
2307
945
 
2308
- context "when provided nil" do
946
+ it_behaves_like 'requires an argument'
947
+ it_behaves_like 'requires a non-nil argument'
2309
948
 
2310
- let(:selection) do
2311
- query.nin(nil)
2312
- end
949
+ context "when provided a single criterion" do
2313
950
 
2314
- it "does not add any criterion" do
2315
- expect(selection.selector).to eq({})
951
+ let(:selection) do
952
+ query.gte(field: 10)
2316
953
  end
2317
954
 
2318
- it "returns the query" do
2319
- expect(selection).to eq(query)
955
+ it "adds the $gte selector" do
956
+ expect(selection.selector).to eq({
957
+ "field" => { "$gte" => 10 }
958
+ })
2320
959
  end
2321
960
 
2322
961
  it "returns a cloned query" do
@@ -2324,17 +963,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
2324
963
  end
2325
964
  end
2326
965
 
2327
- context "when provided a single criterion" do
966
+ context "when provided multiple criterion" do
2328
967
 
2329
- context "when providing an array" do
968
+ context "when the criterion are for different fields" do
2330
969
 
2331
970
  let(:selection) do
2332
- query.nin(field: [ 1, 2 ])
971
+ query.gte(first: 10, second: 15)
2333
972
  end
2334
973
 
2335
- it "adds the $nin selector" do
974
+ it "adds the $gte selectors" do
2336
975
  expect(selection.selector).to eq({
2337
- "field" => { "$nin" => [ 1, 2 ] }
976
+ "first" => { "$gte" => 10 },
977
+ "second" => { "$gte" => 15 }
2338
978
  })
2339
979
  end
2340
980
 
@@ -2342,16 +982,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
2342
982
  expect(selection).to_not equal(query)
2343
983
  end
2344
984
  end
985
+ end
986
+
987
+ context "when chaining the criterion" do
2345
988
 
2346
- context "when providing a range" do
989
+ context "when the criterion are for different fields" do
2347
990
 
2348
991
  let(:selection) do
2349
- query.nin(field: 1..3)
992
+ query.gte(first: 10).gte(second: 15)
2350
993
  end
2351
994
 
2352
- it "adds the $nin selector with converted range" do
995
+ it "adds the $gte selectors" do
2353
996
  expect(selection.selector).to eq({
2354
- "field" => { "$nin" => [ 1, 2, 3 ] }
997
+ "first" => { "$gte" => 10 },
998
+ "second" => { "$gte" => 15 }
2355
999
  })
2356
1000
  end
2357
1001
 
@@ -2360,15 +1004,15 @@ describe Mongoid::Criteria::Queryable::Selectable do
2360
1004
  end
2361
1005
  end
2362
1006
 
2363
- context "when providing a single value" do
1007
+ context "when the criterion are on the same field" do
2364
1008
 
2365
1009
  let(:selection) do
2366
- query.nin(field: 1)
1010
+ query.gte(first: 10).gte(first: 15)
2367
1011
  end
2368
1012
 
2369
- it "adds the $nin selector with wrapped value" do
1013
+ it "overwrites the first $gte selector" do
2370
1014
  expect(selection.selector).to eq({
2371
- "field" => { "$nin" => [ 1 ] }
1015
+ "first" => { "$gte" => 15 }
2372
1016
  })
2373
1017
  end
2374
1018
 
@@ -2377,48 +1021,44 @@ describe Mongoid::Criteria::Queryable::Selectable do
2377
1021
  end
2378
1022
  end
2379
1023
  end
1024
+ end
2380
1025
 
2381
- context "when unioning on the same field" do
1026
+ describe "#in" do
2382
1027
 
2383
- context "when the field is not aliased" do
1028
+ let(:query_method) { :in }
1029
+ let(:operator) { '$in' }
2384
1030
 
2385
- let(:selection) do
2386
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
2387
- end
1031
+ it_behaves_like 'requires an argument'
1032
+ it_behaves_like 'requires a non-nil argument'
2388
1033
 
2389
- it "unions the selection on the field" do
2390
- expect(selection.selector).to eq(
2391
- { "first" => { "$nin" => [ 1, 2, 3, 4 ]}}
2392
- )
2393
- end
2394
- end
1034
+ context "when provided a single criterion" do
2395
1035
 
2396
- context "when the field is aliased" do
1036
+ context "when providing an array" do
2397
1037
 
2398
1038
  let(:selection) do
2399
- query.nin(id: [ 1, 2 ]).union.nin(id: [ 3, 4 ])
1039
+ query.in(field: [ 1, 2 ])
2400
1040
  end
2401
1041
 
2402
- it "unions the selection on the field" do
2403
- expect(selection.selector).to eq(
2404
- { "_id" => { "$nin" => [ 1, 2, 3, 4 ]}}
2405
- )
1042
+ it "adds the $in selector" do
1043
+ expect(selection.selector).to eq({
1044
+ "field" => { "$in" => [ 1, 2 ] }
1045
+ })
2406
1046
  end
2407
- end
2408
- end
2409
1047
 
2410
- context "when provided multiple criterion" do
1048
+ it "returns a cloned query" do
1049
+ expect(selection).to_not equal(query)
1050
+ end
1051
+ end
2411
1052
 
2412
- context "when the criterion are for different fields" do
1053
+ context "when providing a single value" do
2413
1054
 
2414
1055
  let(:selection) do
2415
- query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
1056
+ query.in(field: 1)
2416
1057
  end
2417
1058
 
2418
- it "adds the $nin selectors" do
1059
+ it "adds the $in selector with wrapped value" do
2419
1060
  expect(selection.selector).to eq({
2420
- "first" => { "$nin" => [ 1, 2 ] },
2421
- "second" => { "$nin" => [ 3, 4 ] }
1061
+ "field" => { "$in" => [ 1 ] }
2422
1062
  })
2423
1063
  end
2424
1064
 
@@ -2428,148 +1068,70 @@ describe Mongoid::Criteria::Queryable::Selectable do
2428
1068
  end
2429
1069
  end
2430
1070
 
2431
- context "when chaninning the criterion" do
1071
+ context "when provided multiple criterion" do
2432
1072
 
2433
1073
  context "when the criterion are for different fields" do
2434
1074
 
2435
1075
  let(:selection) do
2436
- query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
1076
+ query.in(first: [ 1, 2 ], second: 3..4)
2437
1077
  end
2438
1078
 
2439
- it "adds the $nin selectors" do
1079
+ it "adds the $in selectors" do
2440
1080
  expect(selection.selector).to eq({
2441
- "first" => { "$nin" => [ 1, 2 ] },
2442
- "second" => { "$nin" => [ 3, 4 ] }
1081
+ "first" => { "$in" => [ 1, 2 ] },
1082
+ "second" => { "$in" => [ 3, 4 ] }
2443
1083
  })
2444
1084
  end
2445
1085
 
2446
1086
  it "returns a cloned query" do
2447
1087
  expect(selection).to_not equal(query)
2448
- end
2449
- end
2450
-
2451
- context "when the criterion are on the same field" do
2452
-
2453
- context "when the stretegy is the default (intersection)" do
2454
-
2455
- let(:selection) do
2456
- query.nin(first: [ 1, 2 ]).nin(first: [ 2, 3 ])
2457
- end
2458
-
2459
- it "intersects the $nin selectors" do
2460
- expect(selection.selector).to eq({
2461
- "first" => { "$nin" => [ 2 ] }
2462
- })
2463
- end
2464
-
2465
- it "returns a cloned query" do
2466
- expect(selection).to_not equal(query)
2467
- end
2468
- end
2469
-
2470
- context "when the stretegy is intersect" do
2471
-
2472
- let(:selection) do
2473
- query.nin(first: [ 1, 2 ]).intersect.nin(first: [ 2, 3 ])
2474
- end
2475
-
2476
- it "intersects the $nin selectors" do
2477
- expect(selection.selector).to eq({
2478
- "first" => { "$nin" => [ 2 ] }
2479
- })
2480
- end
2481
-
2482
- it "returns a cloned query" do
2483
- expect(selection).to_not equal(query)
2484
- end
2485
- end
2486
-
2487
- context "when the stretegy is override" do
2488
-
2489
- let(:selection) do
2490
- query.nin(first: [ 1, 2 ]).override.nin(first: [ 3, 4 ])
2491
- end
2492
-
2493
- it "overwrites the first $nin selector" do
2494
- expect(selection.selector).to eq({
2495
- "first" => { "$nin" => [ 3, 4 ] }
2496
- })
2497
- end
2498
-
2499
- it "returns a cloned query" do
2500
- expect(selection).to_not equal(query)
2501
- end
2502
- end
2503
-
2504
- context "when the stretegy is union" do
2505
-
2506
- let(:selection) do
2507
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
2508
- end
2509
-
2510
- it "unions the $nin selectors" do
2511
- expect(selection.selector).to eq({
2512
- "first" => { "$nin" => [ 1, 2, 3, 4 ] }
2513
- })
2514
- end
2515
-
2516
- it "returns a cloned query" do
2517
- expect(selection).to_not equal(query)
2518
- end
2519
- end
2520
- end
2521
- end
2522
- end
2523
-
2524
- describe "#nor" do
2525
-
2526
- context "when provided no criterion" do
2527
-
2528
- let(:selection) do
2529
- query.nor
2530
- end
2531
-
2532
- it "does not add any criterion" do
2533
- expect(selection.selector).to eq({})
2534
- end
2535
-
2536
- it "returns the query" do
2537
- expect(selection).to eq(query)
2538
- end
2539
-
2540
- it "returns a cloned query" do
2541
- expect(selection).to_not equal(query)
1088
+ end
2542
1089
  end
2543
1090
  end
2544
1091
 
2545
- context "when provided nil" do
1092
+ context "when chaining the criterion" do
2546
1093
 
2547
- let(:selection) do
2548
- query.nor(nil)
2549
- end
1094
+ context "when the criterion are for different fields" do
2550
1095
 
2551
- it "does not add any criterion" do
2552
- expect(selection.selector).to eq({})
2553
- end
1096
+ let(:selection) do
1097
+ query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
1098
+ end
2554
1099
 
2555
- it "returns the query" do
2556
- expect(selection).to eq(query)
1100
+ it "adds the $in selectors" do
1101
+ expect(selection.selector).to eq({
1102
+ "first" => { "$in" => [ 1, 2 ] },
1103
+ "second" => { "$in" => [ 3, 4 ] }
1104
+ })
1105
+ end
1106
+
1107
+ it "returns a cloned query" do
1108
+ expect(selection).to_not equal(query)
1109
+ end
2557
1110
  end
2558
1111
 
2559
- it "returns a cloned query" do
2560
- expect(selection).to_not equal(query)
1112
+ context "when the criterion are on the same field" do
1113
+
1114
+ it_behaves_like 'supports merge strategies'
2561
1115
  end
2562
1116
  end
1117
+ end
1118
+
1119
+ describe "#lt" do
1120
+
1121
+ let(:query_method) { :lt }
1122
+
1123
+ it_behaves_like 'requires an argument'
1124
+ it_behaves_like 'requires a non-nil argument'
2563
1125
 
2564
1126
  context "when provided a single criterion" do
2565
1127
 
2566
1128
  let(:selection) do
2567
- query.nor(field: [ 1, 2 ])
1129
+ query.lt(field: 10)
2568
1130
  end
2569
1131
 
2570
- it "adds the $nor selector" do
1132
+ it "adds the $lt selector" do
2571
1133
  expect(selection.selector).to eq({
2572
- "$nor" => [{"field" => [ 1, 2 ] }]
1134
+ "field" => { "$lt" => 10 }
2573
1135
  })
2574
1136
  end
2575
1137
 
@@ -2580,38 +1142,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2580
1142
 
2581
1143
  context "when provided multiple criterion" do
2582
1144
 
2583
- context "when the criterion are fnor different fields" do
2584
-
2585
- let(:selection) do
2586
- query.nor({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
2587
- end
2588
-
2589
- it "adds the $nor selector" do
2590
- expect(selection.selector).to eq({
2591
- "$nor" => [
2592
- { "first" => [ 1, 2 ] },
2593
- { "second" => [ 3, 4 ] }
2594
- ]
2595
- })
2596
- end
2597
-
2598
- it "returns a cloned query" do
2599
- expect(selection).to_not equal(query)
2600
- end
2601
- end
2602
-
2603
- context "when the criterion are on the same field" do
1145
+ context "when the criterion are for different fields" do
2604
1146
 
2605
1147
  let(:selection) do
2606
- query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1148
+ query.lt(first: 10, second: 15)
2607
1149
  end
2608
1150
 
2609
- it "appends both $nor expressions" do
1151
+ it "adds the $lt selectors" do
2610
1152
  expect(selection.selector).to eq({
2611
- "$nor" => [
2612
- { "first" => [ 1, 2 ] },
2613
- { "first" => [ 3, 4 ] }
2614
- ]
1153
+ "first" => { "$lt" => 10 },
1154
+ "second" => { "$lt" => 15 }
2615
1155
  })
2616
1156
  end
2617
1157
 
@@ -2623,18 +1163,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2623
1163
 
2624
1164
  context "when chaining the criterion" do
2625
1165
 
2626
- context "when the criterion are fnor different fields" do
1166
+ context "when the criterion are for different fields" do
2627
1167
 
2628
1168
  let(:selection) do
2629
- query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
1169
+ query.lt(first: 10).lt(second: 15)
2630
1170
  end
2631
1171
 
2632
- it "adds the $nor selectors" do
1172
+ it "adds the $lt selectors" do
2633
1173
  expect(selection.selector).to eq({
2634
- "$nor" => [
2635
- { "first" => [ 1, 2 ] },
2636
- { "second" => [ 3, 4 ] }
2637
- ]
1174
+ "first" => { "$lt" => 10 },
1175
+ "second" => { "$lt" => 15 }
2638
1176
  })
2639
1177
  end
2640
1178
 
@@ -2646,15 +1184,12 @@ describe Mongoid::Criteria::Queryable::Selectable do
2646
1184
  context "when the criterion are on the same field" do
2647
1185
 
2648
1186
  let(:selection) do
2649
- query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
1187
+ query.lt(first: 10).lt(first: 15)
2650
1188
  end
2651
1189
 
2652
- it "appends both $nor expressions" do
1190
+ it "overwrites the first $lt selector" do
2653
1191
  expect(selection.selector).to eq({
2654
- "$nor" => [
2655
- { "first" => [ 1, 2 ] },
2656
- { "first" => [ 3, 4 ] }
2657
- ]
1192
+ "first" => { "$lt" => 15 }
2658
1193
  })
2659
1194
  end
2660
1195
 
@@ -2665,124 +1200,135 @@ describe Mongoid::Criteria::Queryable::Selectable do
2665
1200
  end
2666
1201
  end
2667
1202
 
2668
- describe "#not" do
1203
+ describe "#lte" do
1204
+
1205
+ let(:query_method) { :lte }
2669
1206
 
2670
- context "when provided no criterion" do
1207
+ it_behaves_like 'requires an argument'
1208
+ it_behaves_like 'requires a non-nil argument'
1209
+
1210
+ context "when provided a single criterion" do
2671
1211
 
2672
1212
  let(:selection) do
2673
- query.not
1213
+ query.lte(field: 10)
2674
1214
  end
2675
1215
 
2676
- it "does not add any criterion" do
2677
- expect(selection.selector).to eq({})
1216
+ it "adds the $lte selector" do
1217
+ expect(selection.selector).to eq({
1218
+ "field" => { "$lte" => 10 }
1219
+ })
2678
1220
  end
2679
1221
 
2680
- it "returns the query" do
2681
- expect(selection).to eq(query)
1222
+ it "returns a cloned query" do
1223
+ expect(selection).to_not equal(query)
2682
1224
  end
1225
+ end
2683
1226
 
2684
- it "returns a non cloned query" do
2685
- expect(selection).to equal(query)
2686
- end
1227
+ context "when provided multiple criterion" do
2687
1228
 
2688
- context "when the following criteria is a query method" do
1229
+ context "when the criterion are for different fields" do
2689
1230
 
2690
1231
  let(:selection) do
2691
- query.not.all(field: [ 1, 2 ])
1232
+ query.lte(first: 10, second: 15)
2692
1233
  end
2693
1234
 
2694
- it "negates the all selection" do
2695
- expect(selection.selector).to eq(
2696
- { "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
2697
- )
1235
+ it "adds the $lte selectors" do
1236
+ expect(selection.selector).to eq({
1237
+ "first" => { "$lte" => 10 },
1238
+ "second" => { "$lte" => 15 }
1239
+ })
2698
1240
  end
2699
1241
 
2700
1242
  it "returns a cloned query" do
2701
1243
  expect(selection).to_not equal(query)
2702
1244
  end
2703
-
2704
- it "removes the negation on the clone" do
2705
- expect(selection).to_not be_negating
2706
- end
2707
1245
  end
1246
+ end
2708
1247
 
2709
- context "when the following criteria is a gt method" do
1248
+ context "when chaining the criterion" do
2710
1249
 
2711
- let(:selection) do
2712
- query.not.gt(age: 50)
2713
- end
1250
+ context "when the criterion are for different fields" do
2714
1251
 
2715
- it "negates the gt selection" do
2716
- expect(selection.selector).to eq(
2717
- { "age" => { "$not" => { "$gt" => 50 }}}
2718
- )
1252
+ let(:selection) do
1253
+ query.lte(first: 10).lte(second: 15)
2719
1254
  end
2720
1255
 
2721
- it "returns a coned query" do
2722
- expect(selection).to_not eq(query)
1256
+ it "adds the $lte selectors" do
1257
+ expect(selection.selector).to eq({
1258
+ "first" => { "$lte" => 10 },
1259
+ "second" => { "$lte" => 15 }
1260
+ })
2723
1261
  end
2724
1262
 
2725
- it "removes the negation on the clone" do
2726
- expect(selection).to_not be_negating
1263
+ it "returns a cloned query" do
1264
+ expect(selection).to_not equal(query)
2727
1265
  end
2728
1266
  end
2729
1267
 
2730
- context "when the following criteria is a where" do
1268
+ context "when the criterion are on the same field" do
2731
1269
 
2732
1270
  let(:selection) do
2733
- query.not.where(field: 1, :other.in => [ 1, 2 ])
1271
+ query.lte(first: 10).lte(first: 15)
2734
1272
  end
2735
1273
 
2736
- it "negates the selection with an operator" do
2737
- expect(selection.selector).to eq(
2738
- { "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
2739
- )
1274
+ it "overwrites the first $lte selector" do
1275
+ expect(selection.selector).to eq({
1276
+ "first" => { "$lte" => 15 }
1277
+ })
2740
1278
  end
2741
1279
 
2742
1280
  it "returns a cloned query" do
2743
1281
  expect(selection).to_not equal(query)
2744
1282
  end
2745
-
2746
- it "removes the negation on the clone" do
2747
- expect(selection).to_not be_negating
2748
- end
2749
1283
  end
1284
+ end
1285
+ end
1286
+
1287
+ describe "#max_distance" do
1288
+
1289
+ let(:query_method) { :max_distance }
1290
+
1291
+ it_behaves_like 'requires an argument'
1292
+ it_behaves_like 'requires a non-nil argument'
1293
+
1294
+ context "when provided a criterion" do
2750
1295
 
2751
- context "when the following criteria is a where with a regexp" do
1296
+ context "when a $near criterion exists on the same field" do
2752
1297
 
2753
1298
  let(:selection) do
2754
- query.not.where(field: 1, other: /test/)
1299
+ query.near(location: [ 1, 1 ]).max_distance(location: 50)
2755
1300
  end
2756
1301
 
2757
- it "negates the selection with an operator" do
2758
- expect(selection.selector).to eq(
2759
- { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
2760
- )
1302
+ it "adds the $maxDistance expression" do
1303
+ expect(selection.selector).to eq({
1304
+ "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
1305
+ })
2761
1306
  end
2762
1307
 
2763
1308
  it "returns a cloned query" do
2764
1309
  expect(selection).to_not equal(query)
2765
1310
  end
2766
-
2767
- it "removes the negation on the clone" do
2768
- expect(selection).to_not be_negating
2769
- end
2770
-
2771
1311
  end
2772
1312
  end
1313
+ end
2773
1314
 
2774
- context "when provided nil" do
1315
+ describe "#mod" do
2775
1316
 
2776
- let(:selection) do
2777
- query.not(nil)
2778
- end
1317
+ let(:query_method) { :mod }
2779
1318
 
2780
- it "does not add any criterion" do
2781
- expect(selection.selector).to eq({})
1319
+ it_behaves_like 'requires an argument'
1320
+ it_behaves_like 'requires a non-nil argument'
1321
+
1322
+ context "when provided a criterion" do
1323
+
1324
+ let(:selection) do
1325
+ query.mod(value: [ 10, 1 ])
2782
1326
  end
2783
1327
 
2784
- it "returns the query" do
2785
- expect(selection).to eq(query)
1328
+ it "adds the $mod expression" do
1329
+ expect(selection.selector).to eq({
1330
+ "value" => { "$mod" => [ 10, 1 ] }
1331
+ })
2786
1332
  end
2787
1333
 
2788
1334
  it "returns a cloned query" do
@@ -2790,15 +1336,70 @@ describe Mongoid::Criteria::Queryable::Selectable do
2790
1336
  end
2791
1337
  end
2792
1338
 
2793
- context "when provided a single criterion" do
1339
+ context "when providing multiple criteria" do
1340
+
1341
+ context "when the fields differ" do
1342
+
1343
+ let(:selection) do
1344
+ query.mod(
1345
+ value: [ 10, 1 ],
1346
+ comments: [ 10, 1 ]
1347
+ )
1348
+ end
1349
+
1350
+ it "adds the $mod expression" do
1351
+ expect(selection.selector).to eq({
1352
+ "value" => { "$mod" => [ 10, 1 ] },
1353
+ "comments" => { "$mod" => [ 10, 1 ] }
1354
+ })
1355
+ end
1356
+
1357
+ it "returns a cloned query" do
1358
+ expect(selection).to_not equal(query)
1359
+ end
1360
+ end
1361
+ end
1362
+
1363
+ context "when chaining multiple criteria" do
1364
+
1365
+ context "when the fields differ" do
1366
+
1367
+ let(:selection) do
1368
+ query.
1369
+ mod(value: [ 10, 1 ]).
1370
+ mod(result: [ 10, 1 ])
1371
+ end
1372
+
1373
+ it "adds the $mod expression" do
1374
+ expect(selection.selector).to eq({
1375
+ "value" => { "$mod" => [ 10, 1 ] },
1376
+ "result" => { "$mod" => [ 10, 1 ] }
1377
+ })
1378
+ end
1379
+
1380
+ it "returns a cloned query" do
1381
+ expect(selection).to_not equal(query)
1382
+ end
1383
+ end
1384
+ end
1385
+ end
1386
+
1387
+ describe "#ne" do
1388
+
1389
+ let(:query_method) { :ne }
1390
+
1391
+ it_behaves_like 'requires an argument'
1392
+ it_behaves_like 'requires a non-nil argument'
1393
+
1394
+ context "when provided a criterion" do
2794
1395
 
2795
1396
  let(:selection) do
2796
- query.not(field: /test/)
1397
+ query.ne(value: 10)
2797
1398
  end
2798
1399
 
2799
- it "adds the $not selector" do
1400
+ it "adds the $ne expression" do
2800
1401
  expect(selection.selector).to eq({
2801
- "field" => { "$not" => /test/ }
1402
+ "value" => { "$ne" => 10 }
2802
1403
  })
2803
1404
  end
2804
1405
 
@@ -2807,18 +1408,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
2807
1408
  end
2808
1409
  end
2809
1410
 
2810
- context "when provided multiple criterion" do
1411
+ context "when providing multiple criteria" do
2811
1412
 
2812
- context "when the criterion are for different fields" do
1413
+ context "when the fields differ" do
2813
1414
 
2814
1415
  let(:selection) do
2815
- query.not(first: /1/, second: /2/)
1416
+ query.ne(
1417
+ value: 10,
1418
+ comments: 10
1419
+ )
2816
1420
  end
2817
1421
 
2818
- it "adds the $not selectors" do
1422
+ it "adds the $ne expression" do
2819
1423
  expect(selection.selector).to eq({
2820
- "first" => { "$not" => /1/ },
2821
- "second" => { "$not" => /2/ }
1424
+ "value" => { "$ne" => 10 },
1425
+ "comments" => { "$ne" => 10 }
2822
1426
  })
2823
1427
  end
2824
1428
 
@@ -2828,18 +1432,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
2828
1432
  end
2829
1433
  end
2830
1434
 
2831
- context "when chaining the criterion" do
1435
+ context "when chaining multiple criteria" do
2832
1436
 
2833
- context "when the criterion are for different fields" do
1437
+ context "when the fields differ" do
2834
1438
 
2835
1439
  let(:selection) do
2836
- query.not(first: /1/).not(second: /2/)
1440
+ query.
1441
+ ne(value: 10).
1442
+ ne(result: 10)
2837
1443
  end
2838
1444
 
2839
- it "adds the $not selectors" do
1445
+ it "adds the $ne expression" do
2840
1446
  expect(selection.selector).to eq({
2841
- "first" => { "$not" => /1/ },
2842
- "second" => { "$not" => /2/ }
1447
+ "value" => { "$ne" => 10 },
1448
+ "result" => { "$ne" => 10 }
2843
1449
  })
2844
1450
  end
2845
1451
 
@@ -2847,16 +1453,48 @@ describe Mongoid::Criteria::Queryable::Selectable do
2847
1453
  expect(selection).to_not equal(query)
2848
1454
  end
2849
1455
  end
1456
+ end
1457
+ end
1458
+
1459
+ describe "#near" do
1460
+
1461
+ let(:query_method) { :near }
1462
+
1463
+ it_behaves_like 'requires an argument'
1464
+ it_behaves_like 'requires a non-nil argument'
1465
+
1466
+ context "when provided a criterion" do
1467
+
1468
+ let(:selection) do
1469
+ query.near(location: [ 20, 21 ])
1470
+ end
1471
+
1472
+ it "adds the $near expression" do
1473
+ expect(selection.selector).to eq({
1474
+ "location" => { "$near" => [ 20, 21 ] }
1475
+ })
1476
+ end
1477
+
1478
+ it "returns a cloned query" do
1479
+ expect(selection).to_not equal(query)
1480
+ end
1481
+ end
2850
1482
 
2851
- context "when the criterion are on the same field" do
1483
+ context "when providing multiple criteria" do
1484
+
1485
+ context "when the fields differ" do
2852
1486
 
2853
1487
  let(:selection) do
2854
- query.not(first: /1/).not(first: /2/)
1488
+ query.near(
1489
+ location: [ 20, 21 ],
1490
+ comments: [ 20, 21 ]
1491
+ )
2855
1492
  end
2856
1493
 
2857
- it "overwrites the first $not selector" do
1494
+ it "adds the $near expression" do
2858
1495
  expect(selection.selector).to eq({
2859
- "first" => { "$not" => /2/ }
1496
+ "location" => { "$near" => [ 20, 21 ] },
1497
+ "comments" => { "$near" => [ 20, 21 ] }
2860
1498
  })
2861
1499
  end
2862
1500
 
@@ -2864,16 +1502,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
2864
1502
  expect(selection).to_not equal(query)
2865
1503
  end
2866
1504
  end
1505
+ end
1506
+
1507
+ context "when chaining multiple criteria" do
2867
1508
 
2868
- context "when the criterion are a double negative" do
1509
+ context "when the fields differ" do
2869
1510
 
2870
1511
  let(:selection) do
2871
- query.not.where(:first.not => /1/)
1512
+ query.
1513
+ near(location: [ 20, 21 ]).
1514
+ near(comments: [ 20, 21 ])
2872
1515
  end
2873
1516
 
2874
- it "does not double the $not selector" do
1517
+ it "adds the $near expression" do
2875
1518
  expect(selection.selector).to eq({
2876
- "first" => { "$not" => /1/ }
1519
+ "location" => { "$near" => [ 20, 21 ] },
1520
+ "comments" => { "$near" => [ 20, 21 ] }
2877
1521
  })
2878
1522
  end
2879
1523
 
@@ -2884,55 +1528,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
2884
1528
  end
2885
1529
  end
2886
1530
 
2887
- describe "#or" do
2888
-
2889
- context "when provided no criterion" do
2890
-
2891
- let(:selection) do
2892
- query.or
2893
- end
2894
-
2895
- it "does not add any criterion" do
2896
- expect(selection.selector).to eq({})
2897
- end
2898
-
2899
- it "returns the query" do
2900
- expect(selection).to eq(query)
2901
- end
2902
-
2903
- it "returns a cloned query" do
2904
- expect(selection).to_not equal(query)
2905
- end
2906
- end
2907
-
2908
- context "when provided nil" do
2909
-
2910
- let(:selection) do
2911
- query.or(nil)
2912
- end
2913
-
2914
- it "does not add any criterion" do
2915
- expect(selection.selector).to eq({})
2916
- end
1531
+ describe "#near_sphere" do
2917
1532
 
2918
- it "returns the query" do
2919
- expect(selection).to eq(query)
2920
- end
1533
+ let(:query_method) { :near_sphere }
2921
1534
 
2922
- it "returns a cloned query" do
2923
- expect(selection).to_not equal(query)
2924
- end
2925
- end
1535
+ it_behaves_like 'requires an argument'
1536
+ it_behaves_like 'requires a non-nil argument'
2926
1537
 
2927
- context "when provided a single criterion" do
1538
+ context "when provided a criterion" do
2928
1539
 
2929
1540
  let(:selection) do
2930
- query.or(field: [ 1, 2 ])
1541
+ query.near_sphere(location: [ 20, 21 ])
2931
1542
  end
2932
1543
 
2933
- it "adds the $or selector" do
1544
+ it "adds the $nearSphere expression" do
2934
1545
  expect(selection.selector).to eq({
2935
- "$or" => [{ "field" => [ 1, 2 ] }]
1546
+ "location" => { "$nearSphere" => [ 20, 21 ] }
2936
1547
  })
2937
1548
  end
2938
1549
 
@@ -2941,20 +1552,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
2941
1552
  end
2942
1553
  end
2943
1554
 
2944
- context "when provided multiple criterion" do
1555
+ context "when providing multiple criteria" do
2945
1556
 
2946
- context "when the criterion are for different fields" do
1557
+ context "when the fields differ" do
2947
1558
 
2948
1559
  let(:selection) do
2949
- query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
1560
+ query.near_sphere(
1561
+ location: [ 20, 21 ],
1562
+ comments: [ 20, 21 ]
1563
+ )
2950
1564
  end
2951
1565
 
2952
- it "adds the $or selector" do
1566
+ it "adds the $nearSphere expression" do
2953
1567
  expect(selection.selector).to eq({
2954
- "$or" => [
2955
- { "first" => [ 1, 2 ] },
2956
- { "second" => [ 3, 4 ] }
2957
- ]
1568
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1569
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
2958
1570
  })
2959
1571
  end
2960
1572
 
@@ -2962,19 +1574,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
2962
1574
  expect(selection).to_not equal(query)
2963
1575
  end
2964
1576
  end
1577
+ end
1578
+
1579
+ context "when chaining multiple criteria" do
2965
1580
 
2966
- context "when a criterion has a selectable key" do
1581
+ context "when the fields differ" do
2967
1582
 
2968
1583
  let(:selection) do
2969
- query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
1584
+ query.
1585
+ near_sphere(location: [ 20, 21 ]).
1586
+ near_sphere(comments: [ 20, 21 ])
2970
1587
  end
2971
1588
 
2972
- it "adds the $or selector" do
1589
+ it "adds the $nearSphere expression" do
2973
1590
  expect(selection.selector).to eq({
2974
- "$or" => [
2975
- { "first" => [ 1, 2 ] },
2976
- { "second" => { "$gt" => 3 }}
2977
- ]
1591
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1592
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
2978
1593
  })
2979
1594
  end
2980
1595
 
@@ -2982,36 +1597,28 @@ describe Mongoid::Criteria::Queryable::Selectable do
2982
1597
  expect(selection).to_not equal(query)
2983
1598
  end
2984
1599
  end
1600
+ end
1601
+ end
2985
1602
 
2986
- context "when the criterion has an aliased field" do
1603
+ describe "#nin" do
2987
1604
 
2988
- let(:selection) do
2989
- query.or({ id: 1 })
2990
- end
1605
+ let(:query_method) { :nin }
1606
+ let(:operator) { '$nin' }
2991
1607
 
2992
- it "adds the $or selector and aliases the field" do
2993
- expect(selection.selector).to eq({
2994
- "$or" => [ { "_id" => 1 } ]
2995
- })
2996
- end
1608
+ it_behaves_like 'requires an argument'
1609
+ it_behaves_like 'requires a non-nil argument'
2997
1610
 
2998
- it "returns a cloned query" do
2999
- expect(selection).to_not equal(query)
3000
- end
3001
- end
1611
+ context "when provided a single criterion" do
3002
1612
 
3003
- context "when a criterion is wrapped in an array" do
1613
+ context "when providing an array" do
3004
1614
 
3005
1615
  let(:selection) do
3006
- query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
1616
+ query.nin(field: [ 1, 2 ])
3007
1617
  end
3008
1618
 
3009
- it "adds the $or selector" do
1619
+ it "adds the $nin selector" do
3010
1620
  expect(selection.selector).to eq({
3011
- "$or" => [
3012
- { "first" => [ 1, 2 ] },
3013
- { "second" => { "$gt" => 3 }}
3014
- ]
1621
+ "field" => { "$nin" => [ 1, 2 ] }
3015
1622
  })
3016
1623
  end
3017
1624
 
@@ -3020,18 +1627,15 @@ describe Mongoid::Criteria::Queryable::Selectable do
3020
1627
  end
3021
1628
  end
3022
1629
 
3023
- context "when the criterion are on the same field" do
1630
+ context "when providing a single value" do
3024
1631
 
3025
1632
  let(:selection) do
3026
- query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1633
+ query.nin(field: 1)
3027
1634
  end
3028
1635
 
3029
- it "appends both $or expressions" do
1636
+ it "adds the $nin selector with wrapped value" do
3030
1637
  expect(selection.selector).to eq({
3031
- "$or" => [
3032
- { "first" => [ 1, 2 ] },
3033
- { "first" => [ 3, 4 ] }
3034
- ]
1638
+ "field" => { "$nin" => [ 1 ] }
3035
1639
  })
3036
1640
  end
3037
1641
 
@@ -3041,20 +1645,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
3041
1645
  end
3042
1646
  end
3043
1647
 
3044
- context "when chaining the criterion" do
1648
+ context "when provided multiple criterion" do
3045
1649
 
3046
1650
  context "when the criterion are for different fields" do
3047
1651
 
3048
1652
  let(:selection) do
3049
- query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
1653
+ query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
3050
1654
  end
3051
1655
 
3052
- it "adds the $or selectors" do
1656
+ it "adds the $nin selectors" do
3053
1657
  expect(selection.selector).to eq({
3054
- "$or" => [
3055
- { "first" => [ 1, 2 ] },
3056
- { "second" => [ 3, 4 ] }
3057
- ]
1658
+ "first" => { "$nin" => [ 1, 2 ] },
1659
+ "second" => { "$nin" => [ 3, 4 ] }
3058
1660
  })
3059
1661
  end
3060
1662
 
@@ -3062,19 +1664,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
3062
1664
  expect(selection).to_not equal(query)
3063
1665
  end
3064
1666
  end
1667
+ end
3065
1668
 
3066
- context "when the criterion are on the same field" do
1669
+ context "when chaining the criterion" do
1670
+
1671
+ context "when the criterion are for different fields" do
3067
1672
 
3068
1673
  let(:selection) do
3069
- query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
1674
+ query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
3070
1675
  end
3071
1676
 
3072
- it "appends both $or expressions" do
1677
+ it "adds the $nin selectors" do
3073
1678
  expect(selection.selector).to eq({
3074
- "$or" => [
3075
- { "first" => [ 1, 2 ] },
3076
- { "first" => [ 3, 4 ] }
3077
- ]
1679
+ "first" => { "$nin" => [ 1, 2 ] },
1680
+ "second" => { "$nin" => [ 3, 4 ] }
3078
1681
  })
3079
1682
  end
3080
1683
 
@@ -3082,48 +1685,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
3082
1685
  expect(selection).to_not equal(query)
3083
1686
  end
3084
1687
  end
3085
- end
3086
- end
3087
-
3088
- describe "#with_size" do
3089
-
3090
- context "when provided no criterion" do
3091
-
3092
- let(:selection) do
3093
- query.with_size
3094
- end
3095
-
3096
- it "does not add any criterion" do
3097
- expect(selection.selector).to eq({})
3098
- end
3099
1688
 
3100
- it "returns the query" do
3101
- expect(selection).to eq(query)
3102
- end
1689
+ context "when the criterion are on the same field" do
3103
1690
 
3104
- it "returns a cloned query" do
3105
- expect(selection).to_not equal(query)
1691
+ it_behaves_like 'supports merge strategies'
3106
1692
  end
3107
1693
  end
1694
+ end
3108
1695
 
3109
- context "when provided nil" do
3110
-
3111
- let(:selection) do
3112
- query.with_size(nil)
3113
- end
3114
-
3115
- it "does not add any criterion" do
3116
- expect(selection.selector).to eq({})
3117
- end
1696
+ describe "#with_size" do
3118
1697
 
3119
- it "returns the query" do
3120
- expect(selection).to eq(query)
3121
- end
1698
+ let(:query_method) { :with_size }
3122
1699
 
3123
- it "returns a cloned query" do
3124
- expect(selection).to_not equal(query)
3125
- end
3126
- end
1700
+ it_behaves_like 'requires an argument'
1701
+ it_behaves_like 'requires a non-nil argument'
3127
1702
 
3128
1703
  context "when provided a single criterion" do
3129
1704
 
@@ -3243,45 +1818,12 @@ describe Mongoid::Criteria::Queryable::Selectable do
3243
1818
  end
3244
1819
  end
3245
1820
 
3246
- describe "#type" do
3247
-
3248
- context "when provided no criterion" do
3249
-
3250
- let(:selection) do
3251
- query.with_type
3252
- end
3253
-
3254
- it "does not add any criterion" do
3255
- expect(selection.selector).to eq({})
3256
- end
3257
-
3258
- it "returns the query" do
3259
- expect(selection).to eq(query)
3260
- end
3261
-
3262
- it "returns a cloned query" do
3263
- expect(selection).to_not equal(query)
3264
- end
3265
- end
3266
-
3267
- context "when provided nil" do
3268
-
3269
- let(:selection) do
3270
- query.with_type(nil)
3271
- end
3272
-
3273
- it "does not add any criterion" do
3274
- expect(selection.selector).to eq({})
3275
- end
1821
+ describe "#with_type" do
3276
1822
 
3277
- it "returns the query" do
3278
- expect(selection).to eq(query)
3279
- end
1823
+ let(:query_method) { :with_type }
3280
1824
 
3281
- it "returns a cloned query" do
3282
- expect(selection).to_not equal(query)
3283
- end
3284
- end
1825
+ it_behaves_like 'requires an argument'
1826
+ it_behaves_like 'requires a non-nil argument'
3285
1827
 
3286
1828
  context "when provided a single criterion" do
3287
1829
 
@@ -3410,7 +1952,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3410
1952
  expect(selection.selector['$text'][:$language]).to eq("fr")
3411
1953
  end
3412
1954
 
3413
- it_behaves_like "a cloning selection"
1955
+ it_behaves_like "returns a cloned query"
3414
1956
  end
3415
1957
  end
3416
1958
 
@@ -3436,6 +1978,8 @@ describe Mongoid::Criteria::Queryable::Selectable do
3436
1978
 
3437
1979
  describe "#where" do
3438
1980
 
1981
+ let(:query_method) { :where }
1982
+
3439
1983
  context "when provided no criterion" do
3440
1984
 
3441
1985
  let(:selection) do
@@ -3455,37 +1999,59 @@ describe Mongoid::Criteria::Queryable::Selectable do
3455
1999
  end
3456
2000
  end
3457
2001
 
3458
- context "when provided nil" do
2002
+ it_behaves_like 'requires a non-nil argument'
3459
2003
 
3460
- let(:selection) do
3461
- query.where(nil)
3462
- end
2004
+ context "when provided a string" do
3463
2005
 
3464
- it "does not add any criterion" do
3465
- expect(selection.selector).to eq({})
2006
+ let(:selection) do
2007
+ query.where("this.value = 10")
3466
2008
  end
3467
2009
 
3468
- it "returns the query" do
3469
- expect(selection).to eq(query)
2010
+ it "adds the $where criterion" do
2011
+ expect(selection.selector).to eq({ "$where" => "this.value = 10" })
3470
2012
  end
3471
2013
 
3472
2014
  it "returns a cloned query" do
3473
2015
  expect(selection).to_not equal(query)
3474
2016
  end
3475
- end
3476
2017
 
3477
- context "when provided a string" do
2018
+ context 'when multiple calls with string argument are made' do
3478
2019
 
3479
- let(:selection) do
3480
- query.where("this.value = 10")
2020
+ let(:selection) do
2021
+ query.where("this.value = 10").where('foo.bar')
2022
+ end
2023
+
2024
+ it 'combines conditions' do
2025
+ expect(selection.selector).to eq(
2026
+ "$where" => "this.value = 10", '$and' => [{'$where' => 'foo.bar'}],
2027
+ )
2028
+ end
3481
2029
  end
3482
2030
 
3483
- it "adds the $where criterion" do
3484
- expect(selection.selector).to eq({ "$where" => "this.value = 10" })
2031
+ context 'when called with string argument and with hash argument' do
2032
+
2033
+ let(:selection) do
2034
+ query.where("this.value = 10").where(foo: 'bar')
2035
+ end
2036
+
2037
+ it 'combines conditions' do
2038
+ expect(selection.selector).to eq(
2039
+ "$where" => "this.value = 10", 'foo' => 'bar',
2040
+ )
2041
+ end
3485
2042
  end
3486
2043
 
3487
- it "returns a cloned query" do
3488
- expect(selection).to_not equal(query)
2044
+ context 'when called with hash argument and with string argument' do
2045
+
2046
+ let(:selection) do
2047
+ query.where(foo: 'bar').where("this.value = 10")
2048
+ end
2049
+
2050
+ it 'combines conditions' do
2051
+ expect(selection.selector).to eq(
2052
+ 'foo' => 'bar', "$where" => "this.value = 10",
2053
+ )
2054
+ end
3489
2055
  end
3490
2056
  end
3491
2057
 
@@ -3884,6 +2450,58 @@ describe Mongoid::Criteria::Queryable::Selectable do
3884
2450
  end
3885
2451
  end
3886
2452
  end
2453
+
2454
+ context 'when using an MQL logical operator manually' do
2455
+ let(:base_query) do
2456
+ query.where(test: 1)
2457
+ end
2458
+
2459
+ let(:selection) do
2460
+ base_query.where(mql_operator => ['hello' => 'world'])
2461
+ end
2462
+
2463
+ shared_examples_for 'adds conditions to existing query' do
2464
+ it 'adds conditions to existing query' do
2465
+ selection.selector.should == {
2466
+ 'test' => 1,
2467
+ mql_operator => ['hello' => 'world'],
2468
+ }
2469
+ end
2470
+ end
2471
+
2472
+ shared_examples_for 'adds conditions to existing query with an extra $and' do
2473
+ it 'adds conditions to existing query' do
2474
+ selection.selector.should == {
2475
+ 'test' => 1,
2476
+ mql_operator => ['hello' => 'world'],
2477
+ }
2478
+ end
2479
+ end
2480
+
2481
+ context '$or' do
2482
+ let(:mql_operator) { '$or' }
2483
+
2484
+ it_behaves_like 'adds conditions to existing query with an extra $and'
2485
+ end
2486
+
2487
+ context '$nor' do
2488
+ let(:mql_operator) { '$nor' }
2489
+
2490
+ it_behaves_like 'adds conditions to existing query with an extra $and'
2491
+ end
2492
+
2493
+ context '$not' do
2494
+ let(:mql_operator) { '$not' }
2495
+
2496
+ it_behaves_like 'adds conditions to existing query'
2497
+ end
2498
+
2499
+ context '$and' do
2500
+ let(:mql_operator) { '$and' }
2501
+
2502
+ it_behaves_like 'adds conditions to existing query'
2503
+ end
2504
+ end
3887
2505
  end
3888
2506
 
3889
2507
  describe Symbol do
@@ -4198,7 +2816,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4198
2816
 
4199
2817
  context "when using the strategies via methods" do
4200
2818
 
4201
- context "when the values are a hash" do
2819
+ context "when different operators are specified" do
4202
2820
 
4203
2821
  let(:selection) do
4204
2822
  query.gt(field: 5).lt(field: 10).ne(field: 7)
@@ -4206,26 +2824,26 @@ describe Mongoid::Criteria::Queryable::Selectable do
4206
2824
 
4207
2825
  it "merges the strategies on the same field" do
4208
2826
  expect(selection.selector).to eq(
4209
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2827
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4210
2828
  )
4211
2829
  end
4212
2830
  end
4213
2831
 
4214
- context "when the values are not hashes" do
2832
+ context "when the same operator is specified" do
4215
2833
 
4216
2834
  let(:selection) do
4217
2835
  query.where(field: 5).where(field: 10)
4218
2836
  end
4219
2837
 
4220
- it "overrides the previous field" do
4221
- expect(selection.selector).to eq({ "field" => 10 })
2838
+ it "combines conditions" do
2839
+ expect(selection.selector).to eq("field" => 5, '$and' => [{'field' => 10}] )
4222
2840
  end
4223
2841
  end
4224
2842
  end
4225
2843
 
4226
2844
  context "when using the strategies via #where" do
4227
2845
 
4228
- context "when the values are a hash" do
2846
+ context "when using complex keys with different operators" do
4229
2847
 
4230
2848
  let(:selection) do
4231
2849
  query.where(:field.gt => 5, :field.lt => 10, :field.ne => 7)
@@ -4233,7 +2851,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4233
2851
 
4234
2852
  it "merges the strategies on the same field" do
4235
2853
  expect(selection.selector).to eq(
4236
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2854
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4237
2855
  )
4238
2856
  end
4239
2857
  end