mongoid 7.1.0.rc0 → 7.2.0.rc1

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 (508) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +6 -6
  5. data/LICENSE +1 -1
  6. data/README.md +14 -7
  7. data/Rakefile +21 -0
  8. data/lib/config/locales/en.yml +42 -6
  9. data/lib/mongoid.rb +26 -2
  10. data/lib/mongoid/association/accessors.rb +37 -2
  11. data/lib/mongoid/association/depending.rb +1 -6
  12. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  14. data/lib/mongoid/association/many.rb +5 -4
  15. data/lib/mongoid/association/proxy.rb +6 -4
  16. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -1
  17. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  18. data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
  19. data/lib/mongoid/association/referenced/eager.rb +29 -9
  20. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  21. data/lib/mongoid/association/referenced/has_many/enumerable.rb +30 -15
  22. data/lib/mongoid/association/referenced/has_many/proxy.rb +11 -3
  23. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  24. data/lib/mongoid/atomic.rb +13 -3
  25. data/lib/mongoid/atomic/modifiers.rb +1 -1
  26. data/lib/mongoid/attributes.rb +28 -20
  27. data/lib/mongoid/attributes/dynamic.rb +1 -1
  28. data/lib/mongoid/clients/factory.rb +19 -2
  29. data/lib/mongoid/clients/options.rb +8 -8
  30. data/lib/mongoid/clients/sessions.rb +20 -4
  31. data/lib/mongoid/clients/storage_options.rb +5 -5
  32. data/lib/mongoid/composable.rb +1 -0
  33. data/lib/mongoid/config.rb +45 -12
  34. data/lib/mongoid/config/options.rb +5 -2
  35. data/lib/mongoid/contextual.rb +5 -4
  36. data/lib/mongoid/contextual/geo_near.rb +3 -2
  37. data/lib/mongoid/contextual/map_reduce.rb +3 -2
  38. data/lib/mongoid/contextual/mongo.rb +25 -5
  39. data/lib/mongoid/copyable.rb +2 -2
  40. data/lib/mongoid/criteria.rb +80 -11
  41. data/lib/mongoid/criteria/modifiable.rb +2 -1
  42. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  43. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -6
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  45. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  46. data/lib/mongoid/criteria/queryable/mergeable.rb +75 -8
  47. data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
  48. data/lib/mongoid/criteria/queryable/selectable.rb +141 -19
  49. data/lib/mongoid/criteria/queryable/selector.rb +3 -3
  50. data/lib/mongoid/criteria/queryable/storable.rb +106 -101
  51. data/lib/mongoid/document.rb +15 -3
  52. data/lib/mongoid/errors.rb +7 -0
  53. data/lib/mongoid/errors/eager_load.rb +2 -0
  54. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +25 -0
  55. data/lib/mongoid/errors/invalid_elem_match_operator.rb +33 -0
  56. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +26 -0
  57. data/lib/mongoid/errors/invalid_expression_operator.rb +28 -0
  58. data/lib/mongoid/errors/invalid_field_operator.rb +33 -0
  59. data/lib/mongoid/errors/invalid_query.rb +41 -0
  60. data/lib/mongoid/errors/no_client_config.rb +2 -2
  61. data/lib/mongoid/errors/no_default_client.rb +1 -1
  62. data/lib/mongoid/extensions/hash.rb +4 -2
  63. data/lib/mongoid/extensions/regexp.rb +1 -1
  64. data/lib/mongoid/factory.rb +27 -10
  65. data/lib/mongoid/fields.rb +2 -1
  66. data/lib/mongoid/fields/standard.rb +2 -1
  67. data/lib/mongoid/fields/validators/macro.rb +26 -10
  68. data/lib/mongoid/findable.rb +55 -18
  69. data/lib/mongoid/indexable.rb +2 -2
  70. data/lib/mongoid/interceptable.rb +5 -1
  71. data/lib/mongoid/matchable.rb +1 -149
  72. data/lib/mongoid/matcher.rb +127 -0
  73. data/lib/mongoid/matcher/all.rb +22 -0
  74. data/lib/mongoid/matcher/and.rb +21 -0
  75. data/lib/mongoid/matcher/elem_match.rb +35 -0
  76. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  77. data/lib/mongoid/matcher/eq.rb +11 -0
  78. data/lib/mongoid/matcher/eq_impl.rb +32 -0
  79. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +21 -0
  80. data/lib/mongoid/matcher/exists.rb +15 -0
  81. data/lib/mongoid/matcher/expression.rb +40 -0
  82. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  83. data/lib/mongoid/matcher/field_expression.rb +63 -0
  84. data/lib/mongoid/matcher/field_operator.rb +52 -0
  85. data/lib/mongoid/matcher/gt.rb +17 -0
  86. data/lib/mongoid/matcher/gte.rb +17 -0
  87. data/lib/mongoid/matcher/in.rb +25 -0
  88. data/lib/mongoid/matcher/lt.rb +17 -0
  89. data/lib/mongoid/matcher/lte.rb +17 -0
  90. data/lib/mongoid/matcher/ne.rb +16 -0
  91. data/lib/mongoid/matcher/nin.rb +11 -0
  92. data/lib/mongoid/matcher/nor.rb +25 -0
  93. data/lib/mongoid/matcher/not.rb +29 -0
  94. data/lib/mongoid/matcher/or.rb +21 -0
  95. data/lib/mongoid/matcher/regex.rb +41 -0
  96. data/lib/mongoid/matcher/size.rb +26 -0
  97. data/lib/mongoid/persistable/deletable.rb +1 -1
  98. data/lib/mongoid/persistable/pushable.rb +11 -2
  99. data/lib/mongoid/persistence_context.rb +6 -6
  100. data/lib/mongoid/query_cache.rb +83 -38
  101. data/lib/mongoid/railties/database.rake +7 -0
  102. data/lib/mongoid/reloadable.rb +2 -2
  103. data/lib/mongoid/serializable.rb +11 -3
  104. data/lib/mongoid/shardable.rb +56 -4
  105. data/lib/mongoid/tasks/database.rake +10 -5
  106. data/lib/mongoid/tasks/database.rb +83 -0
  107. data/lib/mongoid/timestamps/timeless.rb +3 -1
  108. data/lib/mongoid/traversable.rb +111 -4
  109. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  110. data/lib/mongoid/version.rb +1 -1
  111. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
  112. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  113. data/spec/integration/app_spec.rb +254 -0
  114. data/spec/integration/associations/embedded_spec.rb +148 -0
  115. data/spec/integration/associations/has_many_spec.rb +69 -0
  116. data/spec/integration/associations/has_one_spec.rb +69 -0
  117. data/spec/integration/associations/nested_attributes_assignment_spec.rb +116 -0
  118. data/spec/integration/atomic/modifiers_spec.rb +117 -0
  119. data/spec/integration/bson_regexp_raw_spec.rb +20 -0
  120. data/spec/integration/criteria/date_field_spec.rb +41 -0
  121. data/spec/integration/criteria/logical_spec.rb +13 -0
  122. data/spec/integration/discriminator_key_spec.rb +354 -0
  123. data/spec/integration/discriminator_value_spec.rb +207 -0
  124. data/spec/integration/document_spec.rb +22 -0
  125. data/spec/integration/{matchable_spec.rb → matcher_examples_spec.rb} +120 -41
  126. data/spec/integration/matcher_operator_data/all.yml +140 -0
  127. data/spec/integration/matcher_operator_data/and.yml +93 -0
  128. data/spec/integration/matcher_operator_data/elem_match.yml +363 -0
  129. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  130. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  131. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  132. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  133. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  134. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  135. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  136. data/spec/integration/matcher_operator_data/implicit_traversal.yml +16 -0
  137. data/spec/integration/matcher_operator_data/in.yml +194 -0
  138. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  139. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  140. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  141. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  142. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  143. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  144. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  145. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  146. data/spec/integration/matcher_operator_data/not.yml +196 -0
  147. data/spec/integration/matcher_operator_data/or.yml +137 -0
  148. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  149. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  150. data/spec/integration/matcher_operator_data/size.yml +174 -0
  151. data/spec/integration/matcher_operator_spec.rb +100 -0
  152. data/spec/integration/matcher_spec.rb +189 -0
  153. data/spec/integration/server_query_spec.rb +142 -0
  154. data/spec/integration/shardable_spec.rb +149 -0
  155. data/spec/lite_spec_helper.rb +15 -4
  156. data/spec/mongoid/association/accessors_spec.rb +238 -63
  157. data/spec/mongoid/association/depending_spec.rb +78 -26
  158. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +33 -0
  159. data/spec/mongoid/association/embedded/embeds_many_models.rb +20 -0
  160. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  161. data/spec/mongoid/association/embedded/embeds_one_models.rb +1 -0
  162. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  163. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
  164. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  165. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +146 -68
  166. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +462 -187
  167. data/spec/mongoid/association/referenced/has_many_models.rb +9 -0
  168. data/spec/mongoid/association/referenced/has_one_models.rb +9 -0
  169. data/spec/mongoid/atomic/modifiers_spec.rb +47 -0
  170. data/spec/mongoid/atomic_spec.rb +23 -0
  171. data/spec/mongoid/attributes/nested_spec.rb +1 -1
  172. data/spec/mongoid/attributes_spec.rb +19 -7
  173. data/spec/mongoid/changeable_spec.rb +23 -0
  174. data/spec/mongoid/clients/factory_spec.rb +45 -8
  175. data/spec/mongoid/clients/options_spec.rb +11 -11
  176. data/spec/mongoid/clients/sessions_spec.rb +9 -10
  177. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  178. data/spec/mongoid/clients_spec.rb +2 -2
  179. data/spec/mongoid/config_spec.rb +28 -0
  180. data/spec/mongoid/contextual/atomic_spec.rb +22 -11
  181. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  182. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  183. data/spec/mongoid/contextual/mongo_spec.rb +146 -69
  184. data/spec/mongoid/copyable_spec.rb +153 -1
  185. data/spec/mongoid/copyable_spec_models.rb +14 -0
  186. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +1 -1
  187. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  188. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  189. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  190. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  191. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +45 -12
  192. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1051 -392
  193. data/spec/mongoid/criteria/queryable/selectable_spec.rb +136 -82
  194. data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
  195. data/spec/mongoid/criteria_spec.rb +240 -41
  196. data/spec/mongoid/document_fields_spec.rb +29 -0
  197. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  198. data/spec/mongoid/document_spec.rb +89 -15
  199. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  200. data/spec/mongoid/errors/no_client_config_spec.rb +2 -2
  201. data/spec/mongoid/errors/no_client_database_spec.rb +3 -3
  202. data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -3
  203. data/spec/mongoid/factory_spec.rb +261 -28
  204. data/spec/mongoid/fields_spec.rb +72 -3
  205. data/spec/mongoid/findable_spec.rb +32 -0
  206. data/spec/mongoid/indexable_spec.rb +34 -6
  207. data/spec/mongoid/inspectable_spec.rb +29 -2
  208. data/spec/mongoid/interceptable_spec.rb +64 -2
  209. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  210. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +259 -0
  211. data/spec/mongoid/matcher/extract_attribute_spec.rb +47 -0
  212. data/spec/mongoid/persistable/creatable_spec.rb +108 -25
  213. data/spec/mongoid/persistable/deletable_spec.rb +86 -0
  214. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  215. data/spec/mongoid/persistable/savable_spec.rb +174 -16
  216. data/spec/mongoid/query_cache_middleware_spec.rb +16 -3
  217. data/spec/mongoid/query_cache_spec.rb +498 -29
  218. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  219. data/spec/mongoid/reloadable_spec.rb +72 -0
  220. data/spec/mongoid/scopable_spec.rb +2 -1
  221. data/spec/mongoid/serializable_spec.rb +149 -20
  222. data/spec/mongoid/shardable_models.rb +61 -0
  223. data/spec/mongoid/shardable_spec.rb +69 -16
  224. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  225. data/spec/mongoid/tasks/database_spec.rb +1 -1
  226. data/spec/mongoid/traversable_spec.rb +1100 -0
  227. data/spec/spec_helper.rb +4 -33
  228. data/spec/support/child_process_helper.rb +79 -0
  229. data/spec/support/cluster_config.rb +3 -3
  230. data/spec/support/constraints.rb +50 -10
  231. data/spec/support/expectations.rb +3 -1
  232. data/spec/support/helpers.rb +11 -0
  233. data/spec/support/lite_constraints.rb +22 -0
  234. data/spec/{app → support}/models/account.rb +0 -0
  235. data/spec/{app → support}/models/acolyte.rb +0 -0
  236. data/spec/{app → support}/models/actor.rb +1 -1
  237. data/spec/{app → support}/models/actress.rb +0 -0
  238. data/spec/{app → support}/models/address.rb +0 -0
  239. data/spec/{app → support}/models/address_component.rb +0 -0
  240. data/spec/{app → support}/models/address_number.rb +0 -0
  241. data/spec/{app → support}/models/agency.rb +0 -0
  242. data/spec/{app → support}/models/agent.rb +0 -0
  243. data/spec/{app → support}/models/album.rb +0 -0
  244. data/spec/{app → support}/models/alert.rb +0 -0
  245. data/spec/{app → support}/models/animal.rb +0 -0
  246. data/spec/{app → support}/models/answer.rb +0 -0
  247. data/spec/{app → support}/models/appointment.rb +0 -0
  248. data/spec/support/models/armrest.rb +10 -0
  249. data/spec/{app → support}/models/array_field.rb +0 -0
  250. data/spec/{app → support}/models/article.rb +0 -0
  251. data/spec/{app → support}/models/artist.rb +0 -0
  252. data/spec/{app → support}/models/artwork.rb +0 -0
  253. data/spec/{app → support}/models/audio.rb +0 -0
  254. data/spec/{app → support}/models/augmentation.rb +0 -0
  255. data/spec/{app → support}/models/author.rb +0 -0
  256. data/spec/{app → support}/models/baby.rb +0 -0
  257. data/spec/{app → support}/models/band.rb +0 -0
  258. data/spec/{app → support}/models/bar.rb +0 -0
  259. data/spec/{app → support}/models/basic.rb +0 -0
  260. data/spec/{app → support}/models/bed.rb +0 -0
  261. data/spec/{app → support}/models/big_palette.rb +0 -0
  262. data/spec/{app → support}/models/birthday.rb +0 -0
  263. data/spec/{app → support}/models/bomb.rb +0 -0
  264. data/spec/{app → support}/models/book.rb +0 -0
  265. data/spec/{app → support}/models/breed.rb +0 -0
  266. data/spec/{app → support}/models/browser.rb +1 -1
  267. data/spec/{app → support}/models/building.rb +0 -0
  268. data/spec/{app → support}/models/building_address.rb +0 -0
  269. data/spec/{app → support}/models/bus.rb +0 -0
  270. data/spec/{app → support}/models/business.rb +0 -0
  271. data/spec/{app → support}/models/callback_test.rb +0 -0
  272. data/spec/{app → support}/models/canvas.rb +1 -1
  273. data/spec/{app → support}/models/car.rb +0 -0
  274. data/spec/{app → support}/models/cat.rb +0 -0
  275. data/spec/{app → support}/models/category.rb +0 -0
  276. data/spec/{app → support}/models/child.rb +0 -0
  277. data/spec/{app → support}/models/child_doc.rb +0 -0
  278. data/spec/{app → support}/models/church.rb +0 -0
  279. data/spec/{app → support}/models/circle.rb +0 -0
  280. data/spec/{app → support}/models/circuit.rb +0 -0
  281. data/spec/{app → support}/models/circus.rb +0 -0
  282. data/spec/{app → support}/models/code.rb +0 -0
  283. data/spec/support/models/coding.rb +4 -0
  284. data/spec/support/models/coding/pull_request.rb +12 -0
  285. data/spec/{app → support}/models/comment.rb +0 -0
  286. data/spec/{app → support}/models/company.rb +0 -0
  287. data/spec/{app → support}/models/consumption_period.rb +0 -0
  288. data/spec/{app → support}/models/contextable_item.rb +0 -0
  289. data/spec/{app → support}/models/contractor.rb +0 -0
  290. data/spec/{app → support}/models/cookie.rb +0 -0
  291. data/spec/{app → support}/models/country_code.rb +0 -0
  292. data/spec/{app → support}/models/courier_job.rb +0 -0
  293. data/spec/support/models/crate.rb +13 -0
  294. data/spec/support/models/deed.rb +8 -0
  295. data/spec/{app → support}/models/definition.rb +0 -0
  296. data/spec/support/models/delegating_patient.rb +16 -0
  297. data/spec/{app → support}/models/description.rb +0 -0
  298. data/spec/{app → support}/models/dictionary.rb +0 -0
  299. data/spec/{app → support}/models/division.rb +0 -0
  300. data/spec/{app → support}/models/doctor.rb +0 -0
  301. data/spec/{app → support}/models/dog.rb +0 -0
  302. data/spec/{app → support}/models/dokument.rb +0 -0
  303. data/spec/{app → support}/models/draft.rb +0 -0
  304. data/spec/{app → support}/models/dragon.rb +0 -0
  305. data/spec/{app → support}/models/driver.rb +1 -1
  306. data/spec/{app → support}/models/drug.rb +0 -0
  307. data/spec/{app → support}/models/dungeon.rb +0 -0
  308. data/spec/{app → support}/models/edit.rb +0 -0
  309. data/spec/{app → support}/models/email.rb +0 -0
  310. data/spec/{app → support}/models/employer.rb +0 -0
  311. data/spec/{app → support}/models/entry.rb +0 -0
  312. data/spec/{app → support}/models/eraser.rb +0 -0
  313. data/spec/{app → support}/models/even.rb +0 -0
  314. data/spec/{app → support}/models/event.rb +0 -0
  315. data/spec/{app → support}/models/exhibition.rb +0 -0
  316. data/spec/{app → support}/models/exhibitor.rb +0 -0
  317. data/spec/{app → support}/models/explosion.rb +0 -0
  318. data/spec/{app → support}/models/eye.rb +0 -0
  319. data/spec/{app → support}/models/eye_bowl.rb +0 -0
  320. data/spec/{app → support}/models/face.rb +0 -0
  321. data/spec/{app → support}/models/favorite.rb +0 -0
  322. data/spec/{app → support}/models/filesystem.rb +0 -0
  323. data/spec/{app → support}/models/fire_hydrant.rb +0 -0
  324. data/spec/{app → support}/models/firefox.rb +0 -0
  325. data/spec/{app → support}/models/fish.rb +0 -0
  326. data/spec/{app → support}/models/folder.rb +0 -0
  327. data/spec/{app → support}/models/folder_item.rb +0 -0
  328. data/spec/{app → support}/models/fruits.rb +0 -0
  329. data/spec/{app → support}/models/game.rb +0 -0
  330. data/spec/{app → support}/models/ghost.rb +0 -0
  331. data/spec/support/models/guitar.rb +5 -0
  332. data/spec/{app → support}/models/home.rb +0 -0
  333. data/spec/{app → support}/models/house.rb +0 -0
  334. data/spec/{app → support}/models/html_writer.rb +0 -0
  335. data/spec/{app → support}/models/id_key.rb +0 -0
  336. data/spec/support/models/idnodef.rb +8 -0
  337. data/spec/{app → support}/models/image.rb +0 -0
  338. data/spec/{app → support}/models/implant.rb +0 -0
  339. data/spec/support/models/instrument.rb +9 -0
  340. data/spec/{app → support}/models/item.rb +1 -1
  341. data/spec/{app → support}/models/jar.rb +0 -0
  342. data/spec/{app → support}/models/kaleidoscope.rb +0 -0
  343. data/spec/{app → support}/models/kangaroo.rb +0 -0
  344. data/spec/{app → support}/models/label.rb +0 -0
  345. data/spec/{app → support}/models/language.rb +0 -0
  346. data/spec/{app → support}/models/lat_lng.rb +0 -0
  347. data/spec/{app → support}/models/league.rb +0 -0
  348. data/spec/{app → support}/models/learner.rb +0 -0
  349. data/spec/{app → support}/models/line_item.rb +0 -0
  350. data/spec/{app → support}/models/location.rb +0 -0
  351. data/spec/{app → support}/models/login.rb +0 -0
  352. data/spec/{app → support}/models/manufacturer.rb +0 -0
  353. data/spec/{app → support}/models/meat.rb +0 -0
  354. data/spec/{app → support}/models/membership.rb +0 -0
  355. data/spec/{app → support}/models/message.rb +0 -0
  356. data/spec/{app → support}/models/minim.rb +0 -0
  357. data/spec/{app → support}/models/mixed_drink.rb +0 -0
  358. data/spec/support/models/mop.rb +16 -0
  359. data/spec/{app → support}/models/movie.rb +0 -0
  360. data/spec/{app → support}/models/my_hash.rb +0 -0
  361. data/spec/{app → support}/models/name.rb +0 -0
  362. data/spec/{app → support}/models/name_only.rb +0 -0
  363. data/spec/{app → support}/models/node.rb +0 -0
  364. data/spec/{app → support}/models/note.rb +0 -0
  365. data/spec/{app → support}/models/odd.rb +0 -0
  366. data/spec/{app → support}/models/ordered_post.rb +0 -0
  367. data/spec/{app → support}/models/ordered_preference.rb +0 -0
  368. data/spec/{app → support}/models/oscar.rb +0 -0
  369. data/spec/{app → support}/models/other_owner_object.rb +0 -0
  370. data/spec/{app → support}/models/override.rb +0 -0
  371. data/spec/{app → support}/models/ownable.rb +0 -0
  372. data/spec/{app → support}/models/owner.rb +2 -0
  373. data/spec/{app → support}/models/pack.rb +0 -0
  374. data/spec/{app → support}/models/page.rb +0 -0
  375. data/spec/{app → support}/models/page_question.rb +0 -0
  376. data/spec/{app → support}/models/palette.rb +1 -1
  377. data/spec/{app → support}/models/parent.rb +0 -0
  378. data/spec/{app → support}/models/parent_doc.rb +0 -0
  379. data/spec/{app → support}/models/passport.rb +1 -0
  380. data/spec/{app → support}/models/patient.rb +0 -0
  381. data/spec/{app → support}/models/pdf_writer.rb +0 -0
  382. data/spec/{app → support}/models/pencil.rb +0 -0
  383. data/spec/{app → support}/models/person.rb +1 -1
  384. data/spec/{app → support}/models/pet.rb +0 -0
  385. data/spec/{app → support}/models/pet_owner.rb +0 -0
  386. data/spec/{app → support}/models/phone.rb +1 -0
  387. data/spec/support/models/piano.rb +5 -0
  388. data/spec/{app → support}/models/pizza.rb +0 -0
  389. data/spec/{app → support}/models/player.rb +0 -0
  390. data/spec/{app → support}/models/post.rb +0 -0
  391. data/spec/{app → support}/models/post_genre.rb +0 -0
  392. data/spec/{app → support}/models/powerup.rb +0 -0
  393. data/spec/{app → support}/models/preference.rb +0 -0
  394. data/spec/{app → support}/models/princess.rb +0 -0
  395. data/spec/{app → support}/models/product.rb +0 -0
  396. data/spec/support/models/profile.rb +18 -0
  397. data/spec/{app → support}/models/pronunciation.rb +0 -0
  398. data/spec/{app → support}/models/pub.rb +0 -0
  399. data/spec/support/models/publication.rb +5 -0
  400. data/spec/support/models/publication/encyclopedia.rb +12 -0
  401. data/spec/support/models/publication/review.rb +14 -0
  402. data/spec/{app → support}/models/purchase.rb +0 -0
  403. data/spec/{app → support}/models/question.rb +0 -0
  404. data/spec/{app → support}/models/quiz.rb +0 -0
  405. data/spec/{app → support}/models/rating.rb +0 -0
  406. data/spec/{app → support}/models/record.rb +0 -0
  407. data/spec/{app → support}/models/registry.rb +0 -0
  408. data/spec/{app → support}/models/role.rb +0 -0
  409. data/spec/{app → support}/models/root_category.rb +0 -0
  410. data/spec/{app → support}/models/sandwich.rb +0 -0
  411. data/spec/{app → support}/models/scheduler.rb +0 -0
  412. data/spec/{app/models/profile.rb → support/models/scribe.rb} +2 -2
  413. data/spec/support/models/seat.rb +25 -0
  414. data/spec/{app → support}/models/seo.rb +0 -0
  415. data/spec/{app → support}/models/series.rb +0 -0
  416. data/spec/{app → support}/models/server.rb +0 -0
  417. data/spec/{app → support}/models/service.rb +0 -0
  418. data/spec/{app → support}/models/shape.rb +2 -2
  419. data/spec/{app → support}/models/shelf.rb +0 -0
  420. data/spec/{app → support}/models/shipment_address.rb +0 -0
  421. data/spec/{app → support}/models/shipping_container.rb +0 -0
  422. data/spec/{app → support}/models/shipping_pack.rb +0 -0
  423. data/spec/{app → support}/models/shop.rb +0 -0
  424. data/spec/{app → support}/models/short_agent.rb +0 -0
  425. data/spec/{app → support}/models/short_quiz.rb +0 -0
  426. data/spec/{app → support}/models/simple.rb +0 -0
  427. data/spec/{app → support}/models/slave.rb +0 -0
  428. data/spec/{app → support}/models/song.rb +0 -0
  429. data/spec/{app → support}/models/sound.rb +0 -0
  430. data/spec/{app → support}/models/square.rb +0 -0
  431. data/spec/{app → support}/models/staff.rb +0 -0
  432. data/spec/{app → support}/models/store_as_dup_test1.rb +0 -0
  433. data/spec/{app → support}/models/store_as_dup_test2.rb +0 -0
  434. data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  435. data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  436. data/spec/{app → support}/models/strategy.rb +0 -0
  437. data/spec/{app → support}/models/sub_item.rb +0 -0
  438. data/spec/{app → support}/models/subscription.rb +0 -0
  439. data/spec/{app → support}/models/survey.rb +0 -0
  440. data/spec/{app → support}/models/symptom.rb +0 -0
  441. data/spec/support/models/system_role.rb +7 -0
  442. data/spec/{app → support}/models/tag.rb +0 -0
  443. data/spec/{app → support}/models/target.rb +0 -0
  444. data/spec/{app → support}/models/template.rb +0 -0
  445. data/spec/{app → support}/models/thing.rb +0 -0
  446. data/spec/{app → support}/models/title.rb +0 -0
  447. data/spec/{app → support}/models/tool.rb +2 -2
  448. data/spec/{app → support}/models/topping.rb +0 -0
  449. data/spec/support/models/toy.rb +10 -0
  450. data/spec/{app → support}/models/track.rb +0 -0
  451. data/spec/{app → support}/models/translation.rb +0 -0
  452. data/spec/{app → support}/models/tree.rb +0 -0
  453. data/spec/{app → support}/models/truck.rb +2 -0
  454. data/spec/{app → support}/models/updatable.rb +0 -0
  455. data/spec/{app → support}/models/user.rb +0 -0
  456. data/spec/{app → support}/models/user_account.rb +0 -0
  457. data/spec/{app → support}/models/validation_callback.rb +0 -0
  458. data/spec/{app → support}/models/vehicle.rb +7 -2
  459. data/spec/{app → support}/models/version.rb +0 -0
  460. data/spec/{app → support}/models/vertex.rb +0 -0
  461. data/spec/{app → support}/models/vet_visit.rb +0 -0
  462. data/spec/{app → support}/models/video.rb +0 -0
  463. data/spec/{app → support}/models/video_game.rb +0 -0
  464. data/spec/{app → support}/models/weapon.rb +0 -0
  465. data/spec/{app → support}/models/wiki_page.rb +0 -0
  466. data/spec/{app → support}/models/word.rb +0 -0
  467. data/spec/{app → support}/models/word_origin.rb +0 -0
  468. data/spec/{app → support}/models/writer.rb +2 -2
  469. data/spec/support/session_registry.rb +50 -0
  470. data/spec/support/spec_config.rb +13 -5
  471. data/spec/support/spec_organizer.rb +130 -0
  472. metadata +882 -752
  473. metadata.gz.sig +0 -0
  474. data/lib/mongoid/matchable/all.rb +0 -30
  475. data/lib/mongoid/matchable/and.rb +0 -32
  476. data/lib/mongoid/matchable/default.rb +0 -121
  477. data/lib/mongoid/matchable/elem_match.rb +0 -36
  478. data/lib/mongoid/matchable/eq.rb +0 -23
  479. data/lib/mongoid/matchable/exists.rb +0 -25
  480. data/lib/mongoid/matchable/gt.rb +0 -25
  481. data/lib/mongoid/matchable/gte.rb +0 -25
  482. data/lib/mongoid/matchable/in.rb +0 -26
  483. data/lib/mongoid/matchable/lt.rb +0 -25
  484. data/lib/mongoid/matchable/lte.rb +0 -25
  485. data/lib/mongoid/matchable/ne.rb +0 -23
  486. data/lib/mongoid/matchable/nin.rb +0 -24
  487. data/lib/mongoid/matchable/nor.rb +0 -38
  488. data/lib/mongoid/matchable/or.rb +0 -35
  489. data/lib/mongoid/matchable/regexp.rb +0 -30
  490. data/lib/mongoid/matchable/size.rb +0 -23
  491. data/spec/mongoid/matchable/all_spec.rb +0 -34
  492. data/spec/mongoid/matchable/and_spec.rb +0 -190
  493. data/spec/mongoid/matchable/default_spec.rb +0 -140
  494. data/spec/mongoid/matchable/elem_match_spec.rb +0 -109
  495. data/spec/mongoid/matchable/eq_spec.rb +0 -49
  496. data/spec/mongoid/matchable/exists_spec.rb +0 -60
  497. data/spec/mongoid/matchable/gt_spec.rb +0 -89
  498. data/spec/mongoid/matchable/gte_spec.rb +0 -87
  499. data/spec/mongoid/matchable/in_spec.rb +0 -52
  500. data/spec/mongoid/matchable/lt_spec.rb +0 -88
  501. data/spec/mongoid/matchable/lte_spec.rb +0 -88
  502. data/spec/mongoid/matchable/ne_spec.rb +0 -49
  503. data/spec/mongoid/matchable/nin_spec.rb +0 -51
  504. data/spec/mongoid/matchable/nor_spec.rb +0 -210
  505. data/spec/mongoid/matchable/or_spec.rb +0 -134
  506. data/spec/mongoid/matchable/regexp_spec.rb +0 -62
  507. data/spec/mongoid/matchable/size_spec.rb +0 -28
  508. data/spec/mongoid/matchable_spec.rb +0 -856
@@ -74,7 +74,8 @@ module Mongoid
74
74
  # @since 5.1.0
75
75
  def create_with(attrs = {})
76
76
  tap do
77
- (@create_attrs ||= {}).merge!(attrs)
77
+ @create_attrs ||= {}
78
+ @create_attrs.update(attrs)
78
79
  end
79
80
  end
80
81
 
@@ -60,7 +60,7 @@ module Mongoid
60
60
  #
61
61
  # @since 1.0.0
62
62
  def __numeric__(object)
63
- object.to_s =~ /(^[-+]?[0-9]+$)|(\.0+$)|(\.$)/ ? object.to_i : Float(object)
63
+ object.to_s =~ /(\A[-+]?[0-9]+\z)|(\.0+\z)|(\.\z)/ ? object.to_i : Float(object)
64
64
  end
65
65
 
66
66
  # Evolve the object to an integer.
@@ -12,7 +12,7 @@ module Mongoid
12
12
  # Is the object a regexp?
13
13
  #
14
14
  # @example Is the object a regex?
15
- # /^[123]/.regexp?
15
+ # /\A[123]/.regexp?
16
16
  #
17
17
  # @return [ true ] Always true.
18
18
  #
@@ -24,7 +24,7 @@ module Mongoid
24
24
  # Evolve the object into a regex.
25
25
  #
26
26
  # @example Evolve the object to a regex.
27
- # Regexp.evolve("^[123]")
27
+ # Regexp.evolve("\A[123]")
28
28
  #
29
29
  # @param [ Regexp, String ] object The object to evolve.
30
30
  #
@@ -38,7 +38,7 @@ module Mongoid
38
38
  end
39
39
  end
40
40
 
41
- module Raw
41
+ module Raw_
42
42
 
43
43
  # Is the object a regexp?
44
44
  #
@@ -55,7 +55,7 @@ module Mongoid
55
55
  # Evolve the object into a raw bson regex.
56
56
  #
57
57
  # @example Evolve the object to a regex.
58
- # BSON::Regexp::Raw.evolve("^[123]")
58
+ # BSON::Regexp::Raw.evolve("\\A[123]")
59
59
  #
60
60
  # @param [ BSON::Regexp::Raw, String ] object The object to evolve.
61
61
  #
@@ -77,5 +77,5 @@ end
77
77
 
78
78
  ::Regexp.__send__(:include,Mongoid::Criteria::Queryable::Extensions::Regexp)
79
79
  ::Regexp.__send__(:extend, Mongoid::Criteria::Queryable::Extensions::Regexp::ClassMethods)
80
- BSON::Regexp::Raw.__send__(:include,Mongoid::Criteria::Queryable::Extensions::Regexp::Raw)
81
- BSON::Regexp::Raw.__send__(:extend, Mongoid::Criteria::Queryable::Extensions::Regexp::Raw::ClassMethods)
80
+ BSON::Regexp::Raw.__send__(:include,Mongoid::Criteria::Queryable::Extensions::Regexp::Raw_)
81
+ BSON::Regexp::Raw.__send__(:extend, Mongoid::Criteria::Queryable::Extensions::Regexp::Raw_::ClassMethods)
@@ -9,6 +9,18 @@ module Mongoid
9
9
  # This module contains additional time with zone behavior.
10
10
  module TimeWithZone
11
11
 
12
+ # Evolve the time as a date, UTC midnight.
13
+ #
14
+ # @example Evolve the time to a date query format.
15
+ # time.__evolve_date__
16
+ #
17
+ # @return [ Time ] The date at midnight UTC.
18
+ #
19
+ # @since 1.0.0
20
+ def __evolve_date__
21
+ ::Time.utc(year, month, day, 0, 0, 0, 0)
22
+ end
23
+
12
24
  # Evolve the time into a utc time.
13
25
  #
14
26
  # @example Evolve the time.
@@ -33,7 +33,7 @@ module Mongoid
33
33
  #
34
34
  # A yet more more complex example is the following condition:
35
35
  #
36
- # Foo.geo_spacial(:boundary.intersects_point => [1, 10])
36
+ # Foo.geo_spatial(:boundary.intersects_point => [1, 10])
37
37
  #
38
38
  # Processing this condition will cause a Key instance to be created as
39
39
  # follows:
@@ -163,7 +163,7 @@ module Mongoid
163
163
  if expr.is_a?(Selectable)
164
164
  expr = expr.selector
165
165
  end
166
- normalized = _mongoid_normalize_expr(expr)
166
+ normalized = _mongoid_expand_keys(expr)
167
167
  sel.store(operator, result_criteria.push(normalized))
168
168
  end
169
169
  end
@@ -190,9 +190,9 @@ module Mongoid
190
190
  sel = query.selector
191
191
  _mongoid_flatten_arrays(criteria).each do |criterion|
192
192
  if criterion.is_a?(Selectable)
193
- expr = _mongoid_normalize_expr(criterion.selector)
193
+ expr = _mongoid_expand_keys(criterion.selector)
194
194
  else
195
- expr = criterion
195
+ expr = _mongoid_expand_keys(criterion)
196
196
  end
197
197
  if sel.empty?
198
198
  sel.store(operator, [expr])
@@ -212,7 +212,7 @@ module Mongoid
212
212
  # explicitly only expands Array objects and Array subclasses.
213
213
  private def _mongoid_flatten_arrays(array)
214
214
  out = []
215
- pending = array
215
+ pending = array.dup
216
216
  until pending.empty?
217
217
  item = pending.shift
218
218
  if item.nil?
@@ -226,11 +226,78 @@ module Mongoid
226
226
  out
227
227
  end
228
228
 
229
- # @api private
230
- private def _mongoid_normalize_expr(expr)
231
- expr.inject({}) do |hash, (field, value)|
232
- hash.merge!(field.__expr_part__(value.__expand_complex__))
229
+ # Takes a criteria hash and expands Key objects into hashes containing
230
+ # MQL corresponding to said key objects.
231
+ #
232
+ # Ruby does not permit multiple symbol operators. For example,
233
+ # {:foo.gt => 1, :foo.gt => 2} is collapsed to {:foo.gt => 2} by the
234
+ # language. Therefore this method never has to deal with multiple
235
+ # identical operators.
236
+ #
237
+ # Similarly, this method should never need to expand a literal value
238
+ # and an operator at the same time.
239
+ #
240
+ # @param [ Hash ] expr Criteria including Key instances.
241
+ #
242
+ # @return [ Hash ] The expanded criteria.
243
+ private def _mongoid_expand_keys(expr)
244
+ unless expr.is_a?(Hash)
245
+ raise ArgumentError, 'Argument must be a Hash'
246
+ end
247
+
248
+ result = {}
249
+ expr.each do |field, value|
250
+ field.__expr_part__(value.__expand_complex__).each do |k, v|
251
+ if result[k]
252
+ if result[k].is_a?(Hash)
253
+ # Existing value is an operator.
254
+ # If new value is also an operator, ensure there are no
255
+ # conflicts and add
256
+ if v.is_a?(Hash)
257
+ # The new value is also an operator.
258
+ # If there are no conflicts, combine the hashes, otherwise
259
+ # add new conditions to top level with $and.
260
+ if (v.keys & result[k].keys).empty?
261
+ result[k].update(v)
262
+ else
263
+ raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
264
+ result['$and'] ||= []
265
+ result['$and'] << {k => v}
266
+ end
267
+ else
268
+ # The new value is a simple value.
269
+ # If there isn't an $eq operator already in the query,
270
+ # transform the new value into an $eq operator and add it
271
+ # to the existing hash. Otherwise add the new condition
272
+ # with $and to the top level.
273
+ if result[k].key?('$eq')
274
+ raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
275
+ result['$and'] ||= []
276
+ result['$and'] << {k => v}
277
+ else
278
+ result[k].update('$eq' => v)
279
+ end
280
+ end
281
+ else
282
+ # Existing value is a simple value.
283
+ # If we are adding an operator, and the operator is not $eq,
284
+ # convert existing value into $eq and add the new operator
285
+ # to the same hash. Otherwise add the new condition with $and
286
+ # to the top level.
287
+ if v.is_a?(Hash) && !v.key?('$eq')
288
+ result[k] = {'$eq' => result[k]}.update(v)
289
+ else
290
+ raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
291
+ result['$and'] ||= []
292
+ result['$and'] << {k => v}
293
+ end
294
+ end
295
+ else
296
+ result[k] = v
297
+ end
298
+ end
233
299
  end
300
+ result
234
301
  end
235
302
 
236
303
  # Adds the criterion to the existing selection.
@@ -33,7 +33,7 @@ module Mongoid
33
33
  # Add a group operation to the aggregation pipeline.
34
34
  #
35
35
  # @example Add a group operation.
36
- # pipeline.group(:count.sum => 1, :max.max => "likes")
36
+ # pipeline.group(:_id => "foo", :count.sum => 1, :max.max => "likes")
37
37
  #
38
38
  # @param [ Hash ] entry The group entry.
39
39
  #
@@ -76,7 +76,8 @@ module Mongoid
76
76
  # pipeline.unwind(:field)
77
77
  # pipeline.unwind(document)
78
78
  #
79
- # @param [ String, Symbol, Hash ] field_or_doc The name of the field or a document.
79
+ # @param [ String, Symbol, Hash ] field_or_doc A field name or a
80
+ # document.
80
81
  #
81
82
  # @return [ Pipeline ] The pipeline.
82
83
  #
@@ -89,11 +89,27 @@ module Mongoid
89
89
  if new_s.is_a?(Selectable)
90
90
  new_s = new_s.selector
91
91
  end
92
- normalized = _mongoid_normalize_expr(new_s)
92
+ normalized = _mongoid_expand_keys(new_s)
93
93
  normalized.each do |k, v|
94
94
  k = k.to_s
95
- if c.selector[k] || k[0] == ?$
96
- c = c.send(:__multi__, [{k => v}], '$and')
95
+ if c.selector[k]
96
+ # There is already a condition on k.
97
+ # If v is an operator, and all existing conditions are
98
+ # also operators, and v isn't present in existing conditions,
99
+ # we can add to existing conditions.
100
+ # Otherwise use $and.
101
+ if v.is_a?(Hash) &&
102
+ v.length == 1 &&
103
+ (new_k = v.keys.first).start_with?('$') &&
104
+ (existing_kv = c.selector[k]).is_a?(Hash) &&
105
+ !existing_kv.key?(new_k) &&
106
+ existing_kv.keys.all? { |sub_k| sub_k.start_with?('$') }
107
+ then
108
+ merged_v = c.selector[k].merge(v)
109
+ c.selector.store(k, merged_v)
110
+ else
111
+ c = c.send(:__multi__, [k => v], '$and')
112
+ end
97
113
  else
98
114
  c.selector.store(k, v)
99
115
  end
@@ -203,32 +219,44 @@ module Mongoid
203
219
  # Source: https://docs.mongodb.com/manual/reference/operator/query/box/
204
220
  #
205
221
  # @example Add a geo intersect criterion for a line.
206
- # query.geo_spacial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
222
+ # query.geo_spatial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
207
223
  #
208
224
  # @example Add a geo intersect criterion for a point.
209
- # query.geo_spacial(:location.intersects_point => [[ 1, 10 ]])
225
+ # query.geo_spatial(:location.intersects_point => [[ 1, 10 ]])
210
226
  #
211
227
  # @example Add a geo intersect criterion for a polygon.
212
- # query.geo_spacial(:location.intersects_polygon => [[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]])
228
+ # query.geo_spatial(:location.intersects_polygon => [[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]])
213
229
  #
214
230
  # @example Add a geo within criterion for a polygon.
215
- # query.geo_spacial(:location.within_polygon => [[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]])
231
+ # query.geo_spatial(:location.within_polygon => [[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]])
216
232
  #
217
233
  # @example Add a geo within criterion for a box.
218
- # query.geo_spacial(:location.within_box => [[ 1, 10 ], [ 2, 10 ])
234
+ # query.geo_spatial(:location.within_box => [[ 1, 10 ], [ 2, 10 ])
219
235
  #
220
236
  # @param [ Hash ] criterion The criterion.
221
237
  #
222
238
  # @return [ Selectable ] The cloned selectable.
239
+ def geo_spatial(criterion)
240
+ if criterion.nil?
241
+ raise Errors::CriteriaArgumentRequired, :geo_spatial
242
+ end
243
+
244
+ __merge__(criterion)
245
+ end
246
+
247
+ # Alias for +geo_spatial+.
223
248
  #
224
- # @since 2.0.0
249
+ # @deprecated
225
250
  def geo_spacial(criterion)
251
+ # Duplicate method body so that we can raise this exception with
252
+ # geo_spacial as the indicated operator rather than geo_spatial.
226
253
  if criterion.nil?
227
254
  raise Errors::CriteriaArgumentRequired, :geo_spacial
228
255
  end
229
256
 
230
257
  __merge__(criterion)
231
258
  end
259
+
232
260
  key :intersects_line, :override, "$geoIntersects", "$geometry" do |value|
233
261
  { "type" => LINE_STRING, "coordinates" => value }
234
262
  end
@@ -567,17 +595,21 @@ module Mongoid
567
595
  if new_s.is_a?(Selectable)
568
596
  new_s = new_s.selector
569
597
  end
570
- new_s.each do |k, v|
598
+ _mongoid_expand_keys(new_s).each do |k, v|
571
599
  k = k.to_s
572
600
  if c.selector[k] || k[0] == ?$
573
601
  c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
574
602
  else
575
- if v.is_a?(Regexp)
576
- negated_operator = '$not'
603
+ if v.is_a?(Hash)
604
+ c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
577
605
  else
578
- negated_operator = '$ne'
606
+ if v.is_a?(Regexp)
607
+ negated_operator = '$not'
608
+ else
609
+ negated_operator = '$ne'
610
+ end
611
+ c = c.send(:__override__, {k => v}, negated_operator)
579
612
  end
580
- c = c.send(:__override__, {k => v}, negated_operator)
581
613
  end
582
614
  end
583
615
  c
@@ -586,13 +618,34 @@ module Mongoid
586
618
  end
587
619
  key :not, :override, "$not"
588
620
 
589
- # Adds $or selection to the selectable.
621
+ # Creates a disjunction using $or from the existing criteria in the
622
+ # receiver and the provided arguments.
623
+ #
624
+ # This behavior (receiver becoming one of the disjunction operands)
625
+ # matches ActiveRecord's +or+ behavior.
590
626
  #
591
- # @example Add the $or selection.
627
+ # Use +any_of+ to add a disjunction of the arguments as an additional
628
+ # constraint to the criteria already existing in the receiver.
629
+ #
630
+ # Each argument can be a Hash, a Criteria object, an array of
631
+ # Hash or Criteria objects, or a nested array. Nested arrays will be
632
+ # flattened and can be of any depth. Passing arrays is deprecated.
633
+ #
634
+ # @example Add the $or selection where both fields must have the specified values.
592
635
  # selectable.or(field: 1, field: 2)
593
636
  #
594
- # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
595
- # matches or Criteria objects.
637
+ # @example Add the $or selection where either value match is sufficient.
638
+ # selectable.or({field: 1}, {field: 2})
639
+ #
640
+ # @example Same as previous example but using the deprecated array wrap.
641
+ # selectable.or([{field: 1}, {field: 2}])
642
+ #
643
+ # @example Same as previous example, also deprecated.
644
+ # selectable.or([{field: 1}], [{field: 2}])
645
+ #
646
+ # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
647
+ # Multiple key/value pair matches or Criteria objects, or arrays
648
+ # thereof. Passing arrays is deprecated.
596
649
  #
597
650
  # @return [ Selectable ] The new selectable.
598
651
  #
@@ -600,7 +653,73 @@ module Mongoid
600
653
  def or(*criteria)
601
654
  _mongoid_add_top_level_operation('$or', criteria)
602
655
  end
603
- alias :any_of :or
656
+
657
+ # Adds a disjunction of the arguments as an additional constraint
658
+ # to the criteria already existing in the receiver.
659
+ #
660
+ # Use +or+ to make the receiver one of the disjunction operands.
661
+ #
662
+ # Each argument can be a Hash, a Criteria object, an array of
663
+ # Hash or Criteria objects, or a nested array. Nested arrays will be
664
+ # flattened and can be of any depth. Passing arrays is deprecated.
665
+ #
666
+ # @example Add the $or selection where both fields must have the specified values.
667
+ # selectable.any_of(field: 1, field: 2)
668
+ #
669
+ # @example Add the $or selection where either value match is sufficient.
670
+ # selectable.any_of({field: 1}, {field: 2})
671
+ #
672
+ # @example Same as previous example but using the deprecated array wrap.
673
+ # selectable.any_of([{field: 1}, {field: 2}])
674
+ #
675
+ # @example Same as previous example, also deprecated.
676
+ # selectable.any_of([{field: 1}], [{field: 2}])
677
+ #
678
+ # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
679
+ # Multiple key/value pair matches or Criteria objects, or arrays
680
+ # thereof. Passing arrays is deprecated.
681
+ #
682
+ # @return [ Selectable ] The new selectable.
683
+ #
684
+ # @since 1.0.0
685
+ def any_of(*criteria)
686
+ criteria = _mongoid_flatten_arrays(criteria)
687
+ case criteria.length
688
+ when 0
689
+ clone
690
+ when 1
691
+ # When we have a single criteria, any_of behaves like and.
692
+ # Note: criteria can be a Query object, which #where method does
693
+ # not support.
694
+ self.and(*criteria)
695
+ else
696
+ # When we have multiple criteria, combine them all with $or
697
+ # and add the result to self.
698
+ exprs = criteria.map do |criterion|
699
+ if criterion.is_a?(Selectable)
700
+ _mongoid_expand_keys(criterion.selector)
701
+ else
702
+ Hash[criterion.map do |k, v|
703
+ if k.is_a?(Symbol)
704
+ [k.to_s, v]
705
+ else
706
+ [k, v]
707
+ end
708
+ end]
709
+ end
710
+ end
711
+ # Should be able to do:
712
+ #where('$or' => exprs)
713
+ # But since that is broken do instead:
714
+ clone.tap do |query|
715
+ if query.selector['$or']
716
+ query.selector.store('$or', query.selector['$or'] + exprs)
717
+ else
718
+ query.selector.store('$or', exprs)
719
+ end
720
+ end
721
+ end
722
+ end
604
723
 
605
724
  # Add a $size selection for array fields.
606
725
  #
@@ -765,6 +884,9 @@ module Mongoid
765
884
  end
766
885
 
767
886
  clone.tap do |query|
887
+ unless Hash === criterion
888
+ raise Errors::InvalidQuery, "Expression must be a Hash: #{Errors::InvalidQuery.truncate_expr(criterion)}"
889
+ end
768
890
  criterion.each do |field, value|
769
891
  field_s = field.to_s
770
892
  if field_s[0] == ?$