mongoid 7.0.6 → 7.1.2

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 (849) 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 +13 -13
  5. data/README.md +23 -17
  6. data/Rakefile +2 -0
  7. data/lib/config/locales/en.yml +60 -51
  8. data/lib/mongoid.rb +10 -2
  9. data/lib/mongoid/association.rb +9 -6
  10. data/lib/mongoid/association/accessors.rb +95 -52
  11. data/lib/mongoid/association/bindable.rb +7 -5
  12. data/lib/mongoid/association/builders.rb +4 -3
  13. data/lib/mongoid/association/constrainable.rb +4 -2
  14. data/lib/mongoid/association/depending.rb +5 -2
  15. data/lib/mongoid/association/eager_loadable.rb +2 -0
  16. data/lib/mongoid/association/embedded.rb +3 -0
  17. data/lib/mongoid/association/embedded/batchable.rb +4 -2
  18. data/lib/mongoid/association/embedded/cyclic.rb +8 -6
  19. data/lib/mongoid/association/embedded/embedded_in.rb +6 -3
  20. data/lib/mongoid/association/embedded/embedded_in/binding.rb +4 -1
  21. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +8 -2
  22. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +15 -12
  23. data/lib/mongoid/association/embedded/embeds_many.rb +9 -5
  24. data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -2
  25. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +9 -3
  26. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +50 -47
  27. data/lib/mongoid/association/embedded/embeds_one.rb +9 -5
  28. data/lib/mongoid/association/embedded/embeds_one/binding.rb +5 -2
  29. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +10 -4
  30. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +17 -14
  31. data/lib/mongoid/association/macros.rb +38 -36
  32. data/lib/mongoid/association/many.rb +14 -11
  33. data/lib/mongoid/association/marshalable.rb +3 -1
  34. data/lib/mongoid/association/nested.rb +4 -1
  35. data/lib/mongoid/association/nested/many.rb +17 -15
  36. data/lib/mongoid/association/nested/nested_buildable.rb +6 -3
  37. data/lib/mongoid/association/nested/one.rb +11 -9
  38. data/lib/mongoid/association/one.rb +3 -1
  39. data/lib/mongoid/association/options.rb +9 -6
  40. data/lib/mongoid/association/proxy.rb +31 -14
  41. data/lib/mongoid/association/referenced.rb +3 -0
  42. data/lib/mongoid/association/referenced/auto_save.rb +4 -1
  43. data/lib/mongoid/association/referenced/belongs_to.rb +6 -3
  44. data/lib/mongoid/association/referenced/belongs_to/binding.rb +3 -1
  45. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +6 -3
  46. data/lib/mongoid/association/referenced/belongs_to/eager.rb +40 -2
  47. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +16 -14
  48. data/lib/mongoid/association/referenced/counter_cache.rb +2 -0
  49. data/lib/mongoid/association/referenced/eager.rb +37 -15
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +13 -6
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +12 -6
  52. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +5 -2
  53. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +2 -0
  54. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +25 -18
  55. data/lib/mongoid/association/referenced/has_many.rb +7 -4
  56. data/lib/mongoid/association/referenced/has_many/binding.rb +3 -1
  57. data/lib/mongoid/association/referenced/has_many/buildable.rb +5 -2
  58. data/lib/mongoid/association/referenced/has_many/eager.rb +2 -0
  59. data/lib/mongoid/association/referenced/has_many/enumerable.rb +11 -4
  60. data/lib/mongoid/association/referenced/has_many/proxy.rb +46 -43
  61. data/lib/mongoid/association/referenced/has_one.rb +5 -2
  62. data/lib/mongoid/association/referenced/has_one/binding.rb +4 -2
  63. data/lib/mongoid/association/referenced/has_one/buildable.rb +8 -1
  64. data/lib/mongoid/association/referenced/has_one/eager.rb +2 -0
  65. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +11 -9
  66. data/lib/mongoid/association/referenced/has_one/proxy.rb +17 -15
  67. data/lib/mongoid/association/referenced/syncable.rb +7 -5
  68. data/lib/mongoid/association/reflections.rb +7 -5
  69. data/lib/mongoid/association/relatable.rb +17 -14
  70. data/lib/mongoid/atomic.rb +15 -3
  71. data/lib/mongoid/atomic/modifiers.rb +24 -1
  72. data/lib/mongoid/atomic/paths.rb +2 -0
  73. data/lib/mongoid/atomic/paths/embedded.rb +2 -0
  74. data/lib/mongoid/atomic/paths/embedded/many.rb +4 -2
  75. data/lib/mongoid/atomic/paths/embedded/one.rb +4 -2
  76. data/lib/mongoid/atomic/paths/root.rb +4 -2
  77. data/lib/mongoid/attributes.rb +14 -13
  78. data/lib/mongoid/attributes/dynamic.rb +2 -0
  79. data/lib/mongoid/attributes/nested.rb +7 -5
  80. data/lib/mongoid/attributes/processing.rb +8 -6
  81. data/lib/mongoid/attributes/readonly.rb +3 -1
  82. data/lib/mongoid/cacheable.rb +3 -1
  83. data/lib/mongoid/changeable.rb +3 -1
  84. data/lib/mongoid/clients.rb +2 -0
  85. data/lib/mongoid/clients/factory.rb +1 -0
  86. data/lib/mongoid/clients/options.rb +2 -0
  87. data/lib/mongoid/clients/sessions.rb +3 -0
  88. data/lib/mongoid/clients/storage_options.rb +2 -0
  89. data/lib/mongoid/clients/validators.rb +2 -0
  90. data/lib/mongoid/clients/validators/storage.rb +2 -0
  91. data/lib/mongoid/composable.rb +4 -2
  92. data/lib/mongoid/config.rb +53 -10
  93. data/lib/mongoid/config/environment.rb +2 -0
  94. data/lib/mongoid/config/options.rb +20 -12
  95. data/lib/mongoid/config/validators.rb +2 -0
  96. data/lib/mongoid/config/validators/client.rb +2 -0
  97. data/lib/mongoid/config/validators/option.rb +2 -0
  98. data/lib/mongoid/contextual.rb +7 -4
  99. data/lib/mongoid/contextual/aggregable/memory.rb +3 -1
  100. data/lib/mongoid/contextual/aggregable/mongo.rb +3 -1
  101. data/lib/mongoid/contextual/atomic.rb +24 -6
  102. data/lib/mongoid/contextual/command.rb +2 -0
  103. data/lib/mongoid/contextual/geo_near.rb +5 -3
  104. data/lib/mongoid/contextual/map_reduce.rb +5 -2
  105. data/lib/mongoid/contextual/memory.rb +4 -2
  106. data/lib/mongoid/contextual/mongo.rb +6 -1
  107. data/lib/mongoid/contextual/none.rb +2 -0
  108. data/lib/mongoid/contextual/queryable.rb +2 -0
  109. data/lib/mongoid/copyable.rb +3 -1
  110. data/lib/mongoid/criteria.rb +25 -4
  111. data/lib/mongoid/criteria/findable.rb +11 -1
  112. data/lib/mongoid/criteria/includable.rb +8 -6
  113. data/lib/mongoid/criteria/inspectable.rb +2 -0
  114. data/lib/mongoid/criteria/marshalable.rb +2 -0
  115. data/lib/mongoid/criteria/modifiable.rb +4 -1
  116. data/lib/mongoid/criteria/options.rb +2 -0
  117. data/lib/mongoid/criteria/permission.rb +2 -0
  118. data/lib/mongoid/criteria/queryable.rb +7 -2
  119. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -0
  120. data/lib/mongoid/criteria/queryable/expandable.rb +93 -0
  121. data/lib/mongoid/criteria/queryable/extensions.rb +2 -0
  122. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -1
  123. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +3 -1
  124. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -0
  125. data/lib/mongoid/criteria/queryable/extensions/date.rb +3 -1
  126. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +5 -6
  127. data/lib/mongoid/criteria/queryable/extensions/hash.rb +3 -1
  128. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -1
  129. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -2
  130. data/lib/mongoid/criteria/queryable/extensions/object.rb +3 -1
  131. data/lib/mongoid/criteria/queryable/extensions/range.rb +3 -1
  132. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +7 -5
  133. data/lib/mongoid/criteria/queryable/extensions/set.rb +3 -1
  134. data/lib/mongoid/criteria/queryable/extensions/string.rb +3 -1
  135. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  136. data/lib/mongoid/criteria/queryable/extensions/time.rb +4 -2
  137. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +3 -1
  138. data/lib/mongoid/criteria/queryable/key.rb +34 -6
  139. data/lib/mongoid/criteria/queryable/macroable.rb +3 -1
  140. data/lib/mongoid/criteria/queryable/mergeable.rb +153 -11
  141. data/lib/mongoid/criteria/queryable/optional.rb +5 -3
  142. data/lib/mongoid/criteria/queryable/options.rb +2 -0
  143. data/lib/mongoid/criteria/queryable/pipeline.rb +5 -2
  144. data/lib/mongoid/criteria/queryable/selectable.rb +374 -90
  145. data/lib/mongoid/criteria/queryable/selector.rb +38 -5
  146. data/lib/mongoid/criteria/queryable/smash.rb +2 -0
  147. data/lib/mongoid/criteria/queryable/storable.rb +233 -0
  148. data/lib/mongoid/criteria/scopable.rb +2 -0
  149. data/lib/mongoid/document.rb +2 -0
  150. data/lib/mongoid/equality.rb +3 -2
  151. data/lib/mongoid/errors.rb +3 -0
  152. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -2
  153. data/lib/mongoid/errors/callback.rb +2 -0
  154. data/lib/mongoid/errors/criteria_argument_required.rb +19 -0
  155. data/lib/mongoid/errors/delete_restriction.rb +3 -2
  156. data/lib/mongoid/errors/document_not_destroyed.rb +2 -0
  157. data/lib/mongoid/errors/document_not_found.rb +2 -0
  158. data/lib/mongoid/errors/eager_load.rb +6 -2
  159. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -0
  160. data/lib/mongoid/errors/invalid_collection.rb +2 -0
  161. data/lib/mongoid/errors/invalid_config_option.rb +2 -0
  162. data/lib/mongoid/errors/invalid_dependent_strategy.rb +2 -0
  163. data/lib/mongoid/errors/invalid_field.rb +2 -0
  164. data/lib/mongoid/errors/invalid_field_option.rb +2 -0
  165. data/lib/mongoid/errors/invalid_find.rb +2 -0
  166. data/lib/mongoid/errors/invalid_includes.rb +2 -0
  167. data/lib/mongoid/errors/invalid_index.rb +2 -0
  168. data/lib/mongoid/errors/invalid_options.rb +4 -2
  169. data/lib/mongoid/errors/invalid_path.rb +2 -0
  170. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -0
  171. data/lib/mongoid/errors/invalid_relation.rb +4 -2
  172. data/lib/mongoid/errors/invalid_relation_option.rb +4 -2
  173. data/lib/mongoid/errors/invalid_scope.rb +2 -0
  174. data/lib/mongoid/errors/invalid_session_use.rb +2 -0
  175. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -4
  176. data/lib/mongoid/errors/invalid_storage_options.rb +2 -0
  177. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  178. data/lib/mongoid/errors/invalid_time.rb +2 -0
  179. data/lib/mongoid/errors/invalid_value.rb +2 -0
  180. data/lib/mongoid/errors/inverse_not_found.rb +3 -1
  181. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -0
  182. data/lib/mongoid/errors/mixed_relations.rb +2 -0
  183. data/lib/mongoid/errors/mongoid_error.rb +2 -0
  184. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -1
  185. data/lib/mongoid/errors/no_client_config.rb +2 -0
  186. data/lib/mongoid/errors/no_client_database.rb +2 -0
  187. data/lib/mongoid/errors/no_client_hosts.rb +2 -0
  188. data/lib/mongoid/errors/no_clients_config.rb +2 -0
  189. data/lib/mongoid/errors/no_default_client.rb +2 -0
  190. data/lib/mongoid/errors/no_environment.rb +2 -0
  191. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -0
  192. data/lib/mongoid/errors/no_metadata.rb +2 -0
  193. data/lib/mongoid/errors/no_parent.rb +2 -0
  194. data/lib/mongoid/errors/readonly_attribute.rb +2 -0
  195. data/lib/mongoid/errors/readonly_document.rb +2 -0
  196. data/lib/mongoid/errors/scope_overwrite.rb +2 -0
  197. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -0
  198. data/lib/mongoid/errors/unknown_attribute.rb +2 -0
  199. data/lib/mongoid/errors/unknown_model.rb +2 -0
  200. data/lib/mongoid/errors/unsaved_document.rb +2 -0
  201. data/lib/mongoid/errors/unsupported_javascript.rb +2 -0
  202. data/lib/mongoid/errors/validations.rb +2 -0
  203. data/lib/mongoid/evolvable.rb +3 -1
  204. data/lib/mongoid/extensions.rb +2 -0
  205. data/lib/mongoid/extensions/array.rb +23 -6
  206. data/lib/mongoid/extensions/big_decimal.rb +2 -0
  207. data/lib/mongoid/extensions/boolean.rb +2 -0
  208. data/lib/mongoid/extensions/date.rb +13 -3
  209. data/lib/mongoid/extensions/date_time.rb +4 -3
  210. data/lib/mongoid/extensions/decimal128.rb +2 -0
  211. data/lib/mongoid/extensions/false_class.rb +2 -0
  212. data/lib/mongoid/extensions/float.rb +5 -3
  213. data/lib/mongoid/extensions/hash.rb +51 -9
  214. data/lib/mongoid/extensions/integer.rb +5 -3
  215. data/lib/mongoid/extensions/module.rb +2 -0
  216. data/lib/mongoid/extensions/nil_class.rb +2 -0
  217. data/lib/mongoid/extensions/object.rb +16 -4
  218. data/lib/mongoid/extensions/object_id.rb +2 -0
  219. data/lib/mongoid/extensions/range.rb +2 -0
  220. data/lib/mongoid/extensions/regexp.rb +3 -1
  221. data/lib/mongoid/extensions/set.rb +2 -0
  222. data/lib/mongoid/extensions/string.rb +18 -9
  223. data/lib/mongoid/extensions/symbol.rb +2 -0
  224. data/lib/mongoid/extensions/time.rb +14 -0
  225. data/lib/mongoid/extensions/time_with_zone.rb +14 -0
  226. data/lib/mongoid/extensions/true_class.rb +2 -0
  227. data/lib/mongoid/factory.rb +28 -5
  228. data/lib/mongoid/fields.rb +5 -2
  229. data/lib/mongoid/fields/foreign_key.rb +3 -1
  230. data/lib/mongoid/fields/localized.rb +2 -0
  231. data/lib/mongoid/fields/standard.rb +6 -3
  232. data/lib/mongoid/fields/validators.rb +2 -0
  233. data/lib/mongoid/fields/validators/macro.rb +13 -2
  234. data/lib/mongoid/findable.rb +9 -4
  235. data/lib/mongoid/indexable.rb +3 -1
  236. data/lib/mongoid/indexable/specification.rb +3 -1
  237. data/lib/mongoid/indexable/validators/options.rb +2 -0
  238. data/lib/mongoid/inspectable.rb +3 -1
  239. data/lib/mongoid/interceptable.rb +9 -3
  240. data/lib/mongoid/loggable.rb +13 -7
  241. data/lib/mongoid/matchable.rb +2 -0
  242. data/lib/mongoid/matchable/all.rb +2 -0
  243. data/lib/mongoid/matchable/and.rb +2 -0
  244. data/lib/mongoid/matchable/default.rb +2 -0
  245. data/lib/mongoid/matchable/elem_match.rb +2 -0
  246. data/lib/mongoid/matchable/eq.rb +1 -0
  247. data/lib/mongoid/matchable/exists.rb +2 -0
  248. data/lib/mongoid/matchable/gt.rb +2 -0
  249. data/lib/mongoid/matchable/gte.rb +2 -0
  250. data/lib/mongoid/matchable/in.rb +2 -0
  251. data/lib/mongoid/matchable/lt.rb +2 -0
  252. data/lib/mongoid/matchable/lte.rb +2 -0
  253. data/lib/mongoid/matchable/ne.rb +2 -0
  254. data/lib/mongoid/matchable/nin.rb +2 -0
  255. data/lib/mongoid/matchable/nor.rb +2 -1
  256. data/lib/mongoid/matchable/or.rb +2 -0
  257. data/lib/mongoid/matchable/regexp.rb +5 -2
  258. data/lib/mongoid/matchable/size.rb +2 -0
  259. data/lib/mongoid/persistable.rb +133 -15
  260. data/lib/mongoid/persistable/creatable.rb +3 -1
  261. data/lib/mongoid/persistable/deletable.rb +3 -1
  262. data/lib/mongoid/persistable/destroyable.rb +3 -1
  263. data/lib/mongoid/persistable/incrementable.rb +6 -2
  264. data/lib/mongoid/persistable/logical.rb +4 -1
  265. data/lib/mongoid/persistable/poppable.rb +3 -1
  266. data/lib/mongoid/persistable/pullable.rb +3 -1
  267. data/lib/mongoid/persistable/pushable.rb +14 -3
  268. data/lib/mongoid/persistable/renamable.rb +10 -3
  269. data/lib/mongoid/persistable/savable.rb +3 -1
  270. data/lib/mongoid/persistable/settable.rb +3 -1
  271. data/lib/mongoid/persistable/unsettable.rb +8 -3
  272. data/lib/mongoid/persistable/updatable.rb +3 -1
  273. data/lib/mongoid/persistable/upsertable.rb +3 -1
  274. data/lib/mongoid/persistence_context.rb +27 -15
  275. data/lib/mongoid/positional.rb +2 -0
  276. data/lib/mongoid/query_cache.rb +10 -9
  277. data/lib/mongoid/railtie.rb +3 -1
  278. data/lib/mongoid/railties/controller_runtime.rb +4 -1
  279. data/lib/mongoid/railties/database.rake +9 -0
  280. data/lib/mongoid/reloadable.rb +4 -2
  281. data/lib/mongoid/scopable.rb +2 -1
  282. data/lib/mongoid/selectable.rb +3 -1
  283. data/lib/mongoid/serializable.rb +23 -13
  284. data/lib/mongoid/shardable.rb +59 -5
  285. data/lib/mongoid/stateful.rb +3 -1
  286. data/lib/mongoid/tasks/database.rake +12 -5
  287. data/lib/mongoid/tasks/database.rb +50 -0
  288. data/lib/mongoid/threaded.rb +2 -0
  289. data/lib/mongoid/threaded/lifecycle.rb +2 -0
  290. data/lib/mongoid/timestamps.rb +3 -1
  291. data/lib/mongoid/timestamps/created.rb +3 -1
  292. data/lib/mongoid/timestamps/created/short.rb +2 -0
  293. data/lib/mongoid/timestamps/short.rb +2 -0
  294. data/lib/mongoid/timestamps/timeless.rb +6 -2
  295. data/lib/mongoid/timestamps/updated.rb +3 -1
  296. data/lib/mongoid/timestamps/updated/short.rb +2 -0
  297. data/lib/mongoid/touchable.rb +20 -12
  298. data/lib/mongoid/traversable.rb +4 -2
  299. data/lib/mongoid/validatable.rb +7 -5
  300. data/lib/mongoid/validatable/associated.rb +4 -2
  301. data/lib/mongoid/validatable/format.rb +2 -0
  302. data/lib/mongoid/validatable/length.rb +2 -0
  303. data/lib/mongoid/validatable/localizable.rb +2 -0
  304. data/lib/mongoid/validatable/macros.rb +2 -0
  305. data/lib/mongoid/validatable/presence.rb +4 -2
  306. data/lib/mongoid/validatable/queryable.rb +2 -0
  307. data/lib/mongoid/validatable/uniqueness.rb +5 -3
  308. data/lib/mongoid/version.rb +2 -1
  309. data/lib/rails/generators/mongoid/config/config_generator.rb +2 -0
  310. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +44 -29
  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/app/models/account.rb +3 -0
  317. data/spec/app/models/acolyte.rb +3 -0
  318. data/spec/app/models/actor.rb +3 -0
  319. data/spec/app/models/actress.rb +3 -0
  320. data/spec/app/models/address.rb +3 -0
  321. data/spec/app/models/address_component.rb +3 -0
  322. data/spec/app/models/address_number.rb +3 -0
  323. data/spec/app/models/agency.rb +3 -0
  324. data/spec/app/models/agent.rb +3 -0
  325. data/spec/app/models/album.rb +3 -0
  326. data/spec/app/models/alert.rb +3 -0
  327. data/spec/app/models/animal.rb +3 -0
  328. data/spec/app/models/answer.rb +3 -0
  329. data/spec/app/models/appointment.rb +3 -0
  330. data/spec/app/models/array_field.rb +1 -0
  331. data/spec/app/models/article.rb +3 -0
  332. data/spec/app/models/artist.rb +3 -0
  333. data/spec/app/models/artwork.rb +3 -0
  334. data/spec/app/models/audio.rb +3 -0
  335. data/spec/app/models/augmentation.rb +3 -0
  336. data/spec/app/models/author.rb +3 -0
  337. data/spec/app/models/baby.rb +3 -0
  338. data/spec/app/models/band.rb +3 -0
  339. data/spec/app/models/bar.rb +3 -0
  340. data/spec/app/models/basic.rb +3 -0
  341. data/spec/app/models/bed.rb +3 -0
  342. data/spec/app/models/big_palette.rb +3 -0
  343. data/spec/app/models/birthday.rb +3 -0
  344. data/spec/app/models/bomb.rb +3 -0
  345. data/spec/app/models/book.rb +3 -0
  346. data/spec/app/models/breed.rb +3 -0
  347. data/spec/app/models/browser.rb +3 -0
  348. data/spec/app/models/building.rb +3 -0
  349. data/spec/app/models/building_address.rb +3 -0
  350. data/spec/app/models/bus.rb +3 -0
  351. data/spec/app/models/business.rb +3 -0
  352. data/spec/app/models/callback_test.rb +3 -0
  353. data/spec/app/models/canvas.rb +3 -0
  354. data/spec/app/models/car.rb +3 -0
  355. data/spec/app/models/cat.rb +3 -0
  356. data/spec/app/models/category.rb +3 -0
  357. data/spec/app/models/child.rb +3 -0
  358. data/spec/app/models/child_doc.rb +3 -0
  359. data/spec/app/models/church.rb +3 -0
  360. data/spec/app/models/circle.rb +3 -0
  361. data/spec/app/models/circuit.rb +3 -0
  362. data/spec/app/models/circus.rb +3 -0
  363. data/spec/app/models/code.rb +3 -0
  364. data/spec/app/models/coding.rb +4 -0
  365. data/spec/app/models/coding/pull_request.rb +12 -0
  366. data/spec/app/models/comment.rb +3 -0
  367. data/spec/app/models/company.rb +3 -0
  368. data/spec/app/models/consumption_period.rb +3 -0
  369. data/spec/app/models/contextable_item.rb +3 -0
  370. data/spec/app/models/contractor.rb +3 -0
  371. data/spec/app/models/cookie.rb +3 -0
  372. data/spec/app/models/country_code.rb +3 -0
  373. data/spec/app/models/courier_job.rb +3 -0
  374. data/spec/app/models/definition.rb +3 -0
  375. data/spec/app/models/delegating_patient.rb +16 -0
  376. data/spec/app/models/description.rb +3 -0
  377. data/spec/app/models/dictionary.rb +3 -0
  378. data/spec/app/models/division.rb +3 -0
  379. data/spec/app/models/doctor.rb +3 -0
  380. data/spec/app/models/dog.rb +3 -0
  381. data/spec/app/models/dokument.rb +3 -0
  382. data/spec/app/models/draft.rb +3 -0
  383. data/spec/app/models/dragon.rb +3 -0
  384. data/spec/app/models/driver.rb +3 -0
  385. data/spec/app/models/drug.rb +3 -0
  386. data/spec/app/models/dungeon.rb +3 -0
  387. data/spec/app/models/edit.rb +3 -0
  388. data/spec/app/models/email.rb +3 -0
  389. data/spec/app/models/employer.rb +3 -0
  390. data/spec/app/models/entry.rb +3 -0
  391. data/spec/app/models/eraser.rb +3 -0
  392. data/spec/app/models/even.rb +3 -0
  393. data/spec/app/models/event.rb +3 -0
  394. data/spec/app/models/exhibition.rb +3 -0
  395. data/spec/app/models/exhibitor.rb +3 -0
  396. data/spec/app/models/explosion.rb +3 -0
  397. data/spec/app/models/eye.rb +3 -0
  398. data/spec/app/models/eye_bowl.rb +3 -0
  399. data/spec/app/models/face.rb +3 -0
  400. data/spec/app/models/favorite.rb +3 -0
  401. data/spec/app/models/filesystem.rb +3 -0
  402. data/spec/app/models/fire_hydrant.rb +3 -0
  403. data/spec/app/models/firefox.rb +3 -0
  404. data/spec/app/models/fish.rb +3 -0
  405. data/spec/app/models/folder.rb +3 -0
  406. data/spec/app/models/folder_item.rb +3 -0
  407. data/spec/app/models/fruits.rb +3 -0
  408. data/spec/app/models/game.rb +3 -0
  409. data/spec/app/models/ghost.rb +3 -0
  410. data/spec/app/models/home.rb +3 -0
  411. data/spec/app/models/house.rb +3 -0
  412. data/spec/app/models/html_writer.rb +3 -0
  413. data/spec/app/models/id_key.rb +3 -0
  414. data/spec/app/models/image.rb +3 -0
  415. data/spec/app/models/implant.rb +3 -0
  416. data/spec/app/models/item.rb +3 -0
  417. data/spec/app/models/jar.rb +3 -0
  418. data/spec/app/models/kaleidoscope.rb +3 -0
  419. data/spec/app/models/kangaroo.rb +4 -1
  420. data/spec/app/models/label.rb +3 -0
  421. data/spec/app/models/language.rb +3 -0
  422. data/spec/app/models/lat_lng.rb +3 -0
  423. data/spec/app/models/league.rb +3 -0
  424. data/spec/app/models/learner.rb +3 -0
  425. data/spec/app/models/line_item.rb +3 -0
  426. data/spec/app/models/location.rb +3 -0
  427. data/spec/app/models/login.rb +3 -0
  428. data/spec/app/models/manufacturer.rb +3 -0
  429. data/spec/app/models/meat.rb +3 -0
  430. data/spec/app/models/membership.rb +3 -0
  431. data/spec/app/models/message.rb +3 -0
  432. data/spec/app/models/minim.rb +1 -1
  433. data/spec/app/models/mixed_drink.rb +3 -0
  434. data/spec/app/models/movie.rb +3 -0
  435. data/spec/app/models/my_hash.rb +3 -0
  436. data/spec/app/models/name.rb +3 -0
  437. data/spec/app/models/name_only.rb +9 -0
  438. data/spec/app/models/node.rb +3 -0
  439. data/spec/app/models/note.rb +3 -0
  440. data/spec/app/models/odd.rb +3 -0
  441. data/spec/app/models/ordered_post.rb +3 -0
  442. data/spec/app/models/ordered_preference.rb +3 -0
  443. data/spec/app/models/oscar.rb +3 -0
  444. data/spec/app/models/other_owner_object.rb +3 -0
  445. data/spec/app/models/override.rb +3 -0
  446. data/spec/app/models/ownable.rb +3 -0
  447. data/spec/app/models/owner.rb +3 -0
  448. data/spec/app/models/pack.rb +3 -0
  449. data/spec/app/models/page.rb +3 -0
  450. data/spec/app/models/page_question.rb +3 -0
  451. data/spec/app/models/palette.rb +3 -0
  452. data/spec/app/models/parent.rb +3 -0
  453. data/spec/app/models/parent_doc.rb +3 -0
  454. data/spec/app/models/passport.rb +3 -0
  455. data/spec/app/models/patient.rb +3 -0
  456. data/spec/app/models/pdf_writer.rb +3 -0
  457. data/spec/app/models/pencil.rb +3 -0
  458. data/spec/app/models/person.rb +3 -0
  459. data/spec/app/models/pet.rb +3 -0
  460. data/spec/app/models/pet_owner.rb +3 -0
  461. data/spec/app/models/phone.rb +3 -0
  462. data/spec/app/models/pizza.rb +3 -0
  463. data/spec/app/models/player.rb +3 -0
  464. data/spec/app/models/post.rb +3 -0
  465. data/spec/app/models/post_genre.rb +3 -0
  466. data/spec/app/models/powerup.rb +3 -0
  467. data/spec/app/models/preference.rb +3 -0
  468. data/spec/app/models/princess.rb +3 -0
  469. data/spec/app/models/product.rb +3 -0
  470. data/spec/app/models/profile.rb +3 -0
  471. data/spec/app/models/pronunciation.rb +3 -0
  472. data/spec/app/models/pub.rb +3 -0
  473. data/spec/app/models/publication.rb +5 -0
  474. data/spec/app/models/publication/encyclopedia.rb +12 -0
  475. data/spec/app/models/publication/review.rb +14 -0
  476. data/spec/app/models/purchase.rb +3 -0
  477. data/spec/app/models/question.rb +3 -0
  478. data/spec/app/models/quiz.rb +3 -0
  479. data/spec/app/models/rating.rb +3 -0
  480. data/spec/app/models/record.rb +3 -0
  481. data/spec/app/models/registry.rb +3 -0
  482. data/spec/app/models/role.rb +3 -0
  483. data/spec/app/models/root_category.rb +3 -0
  484. data/spec/app/models/sandwich.rb +3 -0
  485. data/spec/app/models/scheduler.rb +3 -0
  486. data/spec/app/models/seo.rb +3 -0
  487. data/spec/app/models/series.rb +3 -0
  488. data/spec/app/models/server.rb +3 -0
  489. data/spec/app/models/service.rb +3 -0
  490. data/spec/app/models/shape.rb +3 -0
  491. data/spec/app/models/shelf.rb +3 -0
  492. data/spec/app/models/shipment_address.rb +3 -0
  493. data/spec/app/models/shipping_container.rb +3 -0
  494. data/spec/app/models/shipping_pack.rb +3 -0
  495. data/spec/app/models/shop.rb +3 -0
  496. data/spec/app/models/short_agent.rb +3 -0
  497. data/spec/app/models/short_quiz.rb +3 -0
  498. data/spec/app/models/simple.rb +3 -0
  499. data/spec/app/models/slave.rb +3 -0
  500. data/spec/app/models/song.rb +3 -0
  501. data/spec/app/models/sound.rb +3 -0
  502. data/spec/app/models/square.rb +3 -0
  503. data/spec/app/models/staff.rb +3 -0
  504. data/spec/app/models/store_as_dup_test1.rb +3 -0
  505. data/spec/app/models/store_as_dup_test2.rb +3 -0
  506. data/spec/app/models/store_as_dup_test3.rb +1 -0
  507. data/spec/app/models/store_as_dup_test4.rb +1 -0
  508. data/spec/app/models/strategy.rb +3 -0
  509. data/spec/app/models/sub_item.rb +3 -0
  510. data/spec/app/models/subscription.rb +3 -0
  511. data/spec/app/models/survey.rb +3 -0
  512. data/spec/app/models/symptom.rb +3 -0
  513. data/spec/app/models/tag.rb +3 -0
  514. data/spec/app/models/target.rb +3 -0
  515. data/spec/app/models/template.rb +3 -0
  516. data/spec/app/models/thing.rb +3 -0
  517. data/spec/app/models/title.rb +3 -0
  518. data/spec/app/models/tool.rb +3 -0
  519. data/spec/app/models/topping.rb +3 -0
  520. data/spec/app/models/track.rb +3 -0
  521. data/spec/app/models/translation.rb +3 -0
  522. data/spec/app/models/tree.rb +3 -0
  523. data/spec/app/models/truck.rb +3 -0
  524. data/spec/app/models/updatable.rb +1 -0
  525. data/spec/app/models/user.rb +3 -0
  526. data/spec/app/models/user_account.rb +3 -0
  527. data/spec/app/models/validation_callback.rb +3 -0
  528. data/spec/app/models/vehicle.rb +3 -0
  529. data/spec/app/models/version.rb +3 -0
  530. data/spec/app/models/vertex.rb +4 -1
  531. data/spec/app/models/vet_visit.rb +3 -0
  532. data/spec/app/models/video.rb +3 -0
  533. data/spec/app/models/video_game.rb +3 -0
  534. data/spec/app/models/weapon.rb +3 -0
  535. data/spec/app/models/wiki_page.rb +3 -0
  536. data/spec/app/models/word.rb +3 -0
  537. data/spec/app/models/word_origin.rb +3 -0
  538. data/spec/app/models/writer.rb +3 -0
  539. data/spec/config/mongoid.yml +1 -0
  540. data/spec/integration/app_spec.rb +192 -0
  541. data/spec/integration/associations/belongs_to_spec.rb +3 -0
  542. data/spec/integration/associations/embedded_spec.rb +175 -0
  543. data/spec/integration/associations/foreign_key_spec.rb +99 -0
  544. data/spec/integration/associations/foreign_key_spec_models.rb +65 -0
  545. data/spec/integration/associations/reverse_population_spec.rb +35 -0
  546. data/spec/integration/associations/reverse_population_spec_models.rb +37 -0
  547. data/spec/integration/criteria/default_scope_spec.rb +21 -0
  548. data/spec/integration/criteria/logical_spec.rb +94 -0
  549. data/spec/integration/document_spec.rb +22 -0
  550. data/spec/integration/i18n_fallbacks_spec.rb +90 -0
  551. data/spec/integration/shardable_spec.rb +133 -0
  552. data/spec/lite_spec_helper.rb +20 -5
  553. data/spec/mongoid/association/accessors_spec.rb +3 -0
  554. data/spec/mongoid/association/auto_save_spec.rb +3 -0
  555. data/spec/mongoid/association/builders_spec.rb +3 -0
  556. data/spec/mongoid/association/constrainable_spec.rb +3 -0
  557. data/spec/mongoid/association/counter_cache_spec.rb +3 -0
  558. data/spec/mongoid/association/depending_spec.rb +3 -0
  559. data/spec/mongoid/association/eager_spec.rb +3 -0
  560. data/spec/mongoid/association/embedded/cyclic_spec.rb +3 -0
  561. data/spec/mongoid/association/embedded/dirty_spec.rb +3 -0
  562. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +3 -0
  563. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +3 -0
  564. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +3 -0
  565. data/spec/mongoid/association/embedded/embedded_in_spec.rb +4 -1
  566. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +3 -0
  567. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +3 -0
  568. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +3 -0
  569. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  570. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +52 -0
  571. data/spec/mongoid/association/embedded/embeds_many_spec.rb +14 -1
  572. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +3 -0
  573. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +3 -0
  574. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +3 -0
  575. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +3 -0
  576. data/spec/mongoid/association/embedded/embeds_one_models.rb +3 -0
  577. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +29 -0
  578. data/spec/mongoid/association/embedded/embeds_one_spec.rb +4 -3
  579. data/spec/mongoid/association/macros_spec.rb +3 -0
  580. data/spec/mongoid/association/nested/many_spec.rb +3 -0
  581. data/spec/mongoid/association/nested/one_spec.rb +3 -0
  582. data/spec/mongoid/association/options_spec.rb +3 -0
  583. data/spec/mongoid/association/polymorphic_spec.rb +3 -0
  584. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +3 -0
  585. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +3 -0
  586. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +205 -10
  587. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +3 -0
  588. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +38 -0
  589. data/spec/mongoid/association/referenced/belongs_to_spec.rb +3 -0
  590. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +3 -0
  591. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +3 -0
  592. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +16 -0
  593. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +26 -5
  594. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +39 -15
  595. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -2
  596. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +40 -0
  597. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +26 -2
  598. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +3 -0
  599. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +3 -0
  600. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +18 -3
  601. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +3 -0
  602. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +1 -0
  603. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +5 -1
  604. data/spec/mongoid/association/referenced/has_many_models.rb +3 -0
  605. data/spec/mongoid/association/referenced/has_many_query_spec.rb +38 -0
  606. data/spec/mongoid/association/referenced/has_many_spec.rb +3 -0
  607. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +3 -0
  608. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +3 -0
  609. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +18 -3
  610. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +3 -0
  611. data/spec/mongoid/association/referenced/has_one_models.rb +3 -0
  612. data/spec/mongoid/association/referenced/has_one_query_spec.rb +38 -0
  613. data/spec/mongoid/association/referenced/has_one_spec.rb +3 -0
  614. data/spec/mongoid/association/reflections_spec.rb +3 -0
  615. data/spec/mongoid/association/syncable_spec.rb +3 -0
  616. data/spec/mongoid/association_spec.rb +3 -0
  617. data/spec/mongoid/atomic/modifiers_spec.rb +3 -0
  618. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +3 -0
  619. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +3 -0
  620. data/spec/mongoid/atomic/paths/root_spec.rb +3 -0
  621. data/spec/mongoid/atomic/paths_spec.rb +3 -0
  622. data/spec/mongoid/atomic_spec.rb +3 -0
  623. data/spec/mongoid/attributes/nested_spec.rb +3 -0
  624. data/spec/mongoid/attributes/readonly_spec.rb +3 -0
  625. data/spec/mongoid/attributes_spec.rb +3 -0
  626. data/spec/mongoid/cacheable_spec.rb +3 -0
  627. data/spec/mongoid/changeable_spec.rb +26 -0
  628. data/spec/mongoid/clients/factory_spec.rb +38 -20
  629. data/spec/mongoid/clients/options_spec.rb +26 -15
  630. data/spec/mongoid/clients/sessions_spec.rb +11 -4
  631. data/spec/mongoid/clients/transactions_spec.rb +26 -11
  632. data/spec/mongoid/clients_spec.rb +5 -2
  633. data/spec/mongoid/composable_spec.rb +3 -0
  634. data/spec/mongoid/config/environment_spec.rb +3 -0
  635. data/spec/mongoid/config/options_spec.rb +23 -3
  636. data/spec/mongoid/config_spec.rb +39 -0
  637. data/spec/mongoid/contextual/aggregable/memory_spec.rb +3 -0
  638. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +3 -0
  639. data/spec/mongoid/contextual/atomic_spec.rb +120 -10
  640. data/spec/mongoid/contextual/geo_near_spec.rb +3 -0
  641. data/spec/mongoid/contextual/map_reduce_spec.rb +23 -5
  642. data/spec/mongoid/contextual/memory_spec.rb +3 -0
  643. data/spec/mongoid/contextual/mongo_spec.rb +81 -53
  644. data/spec/mongoid/contextual/none_spec.rb +3 -0
  645. data/spec/mongoid/copyable_spec.rb +3 -0
  646. data/spec/mongoid/copyable_spec_models.rb +3 -0
  647. data/spec/mongoid/criteria/findable_spec.rb +58 -0
  648. data/spec/mongoid/criteria/inspectable_spec.rb +3 -0
  649. data/spec/mongoid/criteria/marshalable_spec.rb +3 -0
  650. data/spec/mongoid/criteria/modifiable_spec.rb +7 -3
  651. data/spec/mongoid/criteria/options_spec.rb +3 -0
  652. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -0
  653. data/spec/mongoid/criteria/queryable/expandable_spec.rb +135 -0
  654. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +3 -0
  655. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -0
  656. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +3 -0
  657. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -0
  658. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +3 -0
  659. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +36 -17
  660. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +3 -0
  661. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +3 -0
  662. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +3 -0
  663. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +3 -0
  664. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +3 -0
  665. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +3 -0
  666. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +3 -0
  667. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -0
  668. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +10 -7
  669. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +3 -0
  670. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -1
  671. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +3 -0
  672. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +24 -16
  673. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +3 -0
  674. data/spec/mongoid/criteria/queryable/key_spec.rb +3 -0
  675. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +48 -12
  676. data/spec/mongoid/criteria/queryable/optional_spec.rb +3 -0
  677. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -0
  678. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +3 -0
  679. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -0
  680. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1348 -281
  681. data/spec/mongoid/criteria/queryable/selectable_spec.rb +996 -2159
  682. data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -0
  683. data/spec/mongoid/criteria/queryable/smash_spec.rb +3 -0
  684. data/spec/mongoid/criteria/queryable/storable_spec.rb +190 -0
  685. data/spec/mongoid/criteria/scopable_spec.rb +3 -0
  686. data/spec/mongoid/criteria_spec.rb +73 -2
  687. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  688. data/spec/mongoid/document_query_spec.rb +39 -0
  689. data/spec/mongoid/document_spec.rb +3 -0
  690. data/spec/mongoid/equality_spec.rb +3 -0
  691. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +6 -3
  692. data/spec/mongoid/errors/callback_spec.rb +3 -0
  693. data/spec/mongoid/errors/delete_restriction_spec.rb +3 -0
  694. data/spec/mongoid/errors/document_not_destroyed_spec.rb +3 -0
  695. data/spec/mongoid/errors/document_not_found_spec.rb +3 -0
  696. data/spec/mongoid/errors/eager_load_spec.rb +3 -0
  697. data/spec/mongoid/errors/invalid_collection_spec.rb +3 -0
  698. data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -0
  699. data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -0
  700. data/spec/mongoid/errors/invalid_field_spec.rb +3 -0
  701. data/spec/mongoid/errors/invalid_find_spec.rb +3 -0
  702. data/spec/mongoid/errors/invalid_includes_spec.rb +3 -0
  703. data/spec/mongoid/errors/invalid_index_spec.rb +3 -0
  704. data/spec/mongoid/errors/invalid_options_spec.rb +5 -2
  705. data/spec/mongoid/errors/invalid_path_spec.rb +3 -0
  706. data/spec/mongoid/errors/invalid_relation_spec.rb +5 -2
  707. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -0
  708. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -0
  709. data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -0
  710. data/spec/mongoid/errors/invalid_time_spec.rb +3 -0
  711. data/spec/mongoid/errors/inverse_not_found_spec.rb +4 -1
  712. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +3 -0
  713. data/spec/mongoid/errors/mixed_relations_spec.rb +3 -0
  714. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -0
  715. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +6 -3
  716. data/spec/mongoid/errors/no_client_config_spec.rb +3 -0
  717. data/spec/mongoid/errors/no_client_database_spec.rb +3 -0
  718. data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -0
  719. data/spec/mongoid/errors/no_clients_config_spec.rb +3 -0
  720. data/spec/mongoid/errors/no_environment_spec.rb +3 -0
  721. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -0
  722. data/spec/mongoid/errors/no_metadata_spec.rb +5 -2
  723. data/spec/mongoid/errors/no_parent_spec.rb +4 -1
  724. data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -0
  725. data/spec/mongoid/errors/readonly_document_spec.rb +3 -0
  726. data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -0
  727. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -0
  728. data/spec/mongoid/errors/unknown_attribute_spec.rb +3 -0
  729. data/spec/mongoid/errors/unsaved_document_spec.rb +4 -1
  730. data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -0
  731. data/spec/mongoid/errors/validations_spec.rb +3 -0
  732. data/spec/mongoid/extensions/array_spec.rb +26 -43
  733. data/spec/mongoid/extensions/big_decimal_spec.rb +3 -0
  734. data/spec/mongoid/extensions/binary_spec.rb +3 -0
  735. data/spec/mongoid/extensions/boolean_spec.rb +3 -0
  736. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +336 -0
  737. data/spec/mongoid/extensions/date_spec.rb +9 -160
  738. data/spec/mongoid/extensions/date_time_spec.rb +18 -60
  739. data/spec/mongoid/extensions/decimal128_spec.rb +3 -0
  740. data/spec/mongoid/extensions/false_class_spec.rb +3 -0
  741. data/spec/mongoid/extensions/float_spec.rb +18 -3
  742. data/spec/mongoid/extensions/hash_spec.rb +106 -0
  743. data/spec/mongoid/extensions/integer_spec.rb +15 -2
  744. data/spec/mongoid/extensions/module_spec.rb +3 -0
  745. data/spec/mongoid/extensions/nil_class_spec.rb +3 -0
  746. data/spec/mongoid/extensions/object_id_spec.rb +3 -0
  747. data/spec/mongoid/extensions/object_spec.rb +14 -24
  748. data/spec/mongoid/extensions/range_spec.rb +3 -0
  749. data/spec/mongoid/extensions/regexp_spec.rb +3 -0
  750. data/spec/mongoid/extensions/set_spec.rb +3 -0
  751. data/spec/mongoid/extensions/string_spec.rb +60 -26
  752. data/spec/mongoid/extensions/symbol_spec.rb +3 -0
  753. data/spec/mongoid/extensions/time_spec.rb +30 -0
  754. data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -0
  755. data/spec/mongoid/extensions/true_class_spec.rb +3 -0
  756. data/spec/mongoid/extensions_spec.rb +3 -0
  757. data/spec/mongoid/factory_spec.rb +27 -0
  758. data/spec/mongoid/fields/foreign_key_spec.rb +3 -0
  759. data/spec/mongoid/fields/localized_spec.rb +3 -0
  760. data/spec/mongoid/fields/standard_spec.rb +3 -0
  761. data/spec/mongoid/fields_spec.rb +18 -0
  762. data/spec/mongoid/findable_spec.rb +3 -0
  763. data/spec/mongoid/indexable/specification_spec.rb +3 -0
  764. data/spec/mongoid/indexable_spec.rb +9 -4
  765. data/spec/mongoid/inspectable_spec.rb +3 -0
  766. data/spec/mongoid/interceptable_spec.rb +65 -0
  767. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  768. data/spec/mongoid/loggable_spec.rb +3 -0
  769. data/spec/mongoid/matchable/all_spec.rb +3 -0
  770. data/spec/mongoid/matchable/and_spec.rb +3 -0
  771. data/spec/mongoid/matchable/default_spec.rb +4 -1
  772. data/spec/mongoid/matchable/elem_match_spec.rb +3 -0
  773. data/spec/mongoid/matchable/eq_spec.rb +1 -0
  774. data/spec/mongoid/matchable/exists_spec.rb +3 -0
  775. data/spec/mongoid/matchable/gt_spec.rb +3 -0
  776. data/spec/mongoid/matchable/gte_spec.rb +3 -0
  777. data/spec/mongoid/matchable/in_spec.rb +3 -0
  778. data/spec/mongoid/matchable/lt_spec.rb +3 -0
  779. data/spec/mongoid/matchable/lte_spec.rb +3 -0
  780. data/spec/mongoid/matchable/ne_spec.rb +3 -0
  781. data/spec/mongoid/matchable/nin_spec.rb +3 -0
  782. data/spec/mongoid/matchable/nor_spec.rb +1 -0
  783. data/spec/mongoid/matchable/or_spec.rb +3 -0
  784. data/spec/mongoid/matchable/regexp_spec.rb +5 -2
  785. data/spec/mongoid/matchable/size_spec.rb +3 -0
  786. data/spec/mongoid/matchable_spec.rb +5 -2
  787. data/spec/mongoid/persistable/creatable_spec.rb +3 -0
  788. data/spec/mongoid/persistable/deletable_spec.rb +3 -0
  789. data/spec/mongoid/persistable/destroyable_spec.rb +3 -0
  790. data/spec/mongoid/persistable/incrementable_spec.rb +17 -0
  791. data/spec/mongoid/persistable/logical_spec.rb +17 -0
  792. data/spec/mongoid/persistable/poppable_spec.rb +17 -0
  793. data/spec/mongoid/persistable/pullable_spec.rb +31 -0
  794. data/spec/mongoid/persistable/pushable_spec.rb +86 -1
  795. data/spec/mongoid/persistable/renamable_spec.rb +17 -0
  796. data/spec/mongoid/persistable/savable_spec.rb +3 -0
  797. data/spec/mongoid/persistable/settable_spec.rb +17 -0
  798. data/spec/mongoid/persistable/unsettable_spec.rb +17 -0
  799. data/spec/mongoid/persistable/updatable_spec.rb +3 -0
  800. data/spec/mongoid/persistable/upsertable_spec.rb +3 -0
  801. data/spec/mongoid/persistable_spec.rb +85 -8
  802. data/spec/mongoid/persistence_context_spec.rb +3 -0
  803. data/spec/mongoid/positional_spec.rb +3 -0
  804. data/spec/mongoid/query_cache_middleware_spec.rb +48 -0
  805. data/spec/mongoid/query_cache_spec.rb +5 -45
  806. data/spec/mongoid/relations/proxy_spec.rb +4 -1
  807. data/spec/mongoid/reloadable_spec.rb +3 -0
  808. data/spec/mongoid/scopable_spec.rb +5 -1
  809. data/spec/mongoid/selectable_spec.rb +3 -0
  810. data/spec/mongoid/serializable_spec.rb +132 -18
  811. data/spec/mongoid/shardable_models.rb +61 -0
  812. data/spec/mongoid/shardable_spec.rb +72 -16
  813. data/spec/mongoid/stateful_spec.rb +3 -0
  814. data/spec/mongoid/tasks/database_rake_spec.rb +16 -13
  815. data/spec/mongoid/tasks/database_spec.rb +4 -1
  816. data/spec/mongoid/threaded_spec.rb +3 -0
  817. data/spec/mongoid/timestamps/created/short_spec.rb +3 -0
  818. data/spec/mongoid/timestamps/created_spec.rb +3 -0
  819. data/spec/mongoid/timestamps/timeless_spec.rb +3 -0
  820. data/spec/mongoid/timestamps/updated/short_spec.rb +3 -0
  821. data/spec/mongoid/timestamps/updated_spec.rb +3 -0
  822. data/spec/mongoid/timestamps_spec.rb +3 -0
  823. data/spec/mongoid/touchable_spec.rb +49 -3
  824. data/spec/mongoid/traversable_spec.rb +3 -0
  825. data/spec/mongoid/validatable/associated_spec.rb +3 -0
  826. data/spec/mongoid/validatable/format_spec.rb +3 -0
  827. data/spec/mongoid/validatable/length_spec.rb +3 -0
  828. data/spec/mongoid/validatable/numericality_spec.rb +3 -0
  829. data/spec/mongoid/validatable/presence_spec.rb +3 -0
  830. data/spec/mongoid/validatable/uniqueness_spec.rb +3 -0
  831. data/spec/mongoid/validatable_spec.rb +3 -0
  832. data/spec/mongoid_spec.rb +3 -0
  833. data/spec/rails/controller_extension/controller_runtime_spec.rb +4 -1
  834. data/spec/rails/mongoid_spec.rb +5 -2
  835. data/spec/spec_helper.rb +21 -44
  836. data/spec/support/authorization.rb +3 -0
  837. data/spec/support/child_process_helper.rb +76 -0
  838. data/spec/support/cluster_config.rb +3 -3
  839. data/spec/support/constraints.rb +185 -30
  840. data/spec/support/expectations.rb +6 -1
  841. data/spec/support/helpers.rb +11 -0
  842. data/spec/support/lite_constraints.rb +22 -0
  843. data/spec/support/macros.rb +1 -0
  844. data/spec/support/shared/time.rb +54 -0
  845. data/spec/support/spec_config.rb +15 -4
  846. metadata +544 -472
  847. metadata.gz.sig +0 -0
  848. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  849. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
5
7
 
6
- # Adds macro behaviour for adding symbol methods.
8
+ # Adds macro behavior for adding symbol methods.
7
9
  module Macroable
8
10
 
9
11
  # Adds a method on Symbol for convenience in where queries for the
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
5
7
 
6
- # Contains behaviour for merging existing selection with new selection.
8
+ # Contains behavior for merging existing selection with new selection.
7
9
  module Mergeable
8
10
 
9
11
  # @attribute [rw] strategy The name of the current strategy.
@@ -50,12 +52,13 @@ module Mongoid
50
52
  # @example Reset the strategies.
51
53
  # mergeable.reset_strategies!
52
54
  #
53
- # @return [ nil ] nil.
55
+ # @return [ Criteria ] self.
54
56
  #
55
57
  # @since 1.0.0
56
58
  def reset_strategies!
57
59
  self.strategy = nil
58
60
  self.negating = nil
61
+ self
59
62
  end
60
63
 
61
64
  private
@@ -133,34 +136,170 @@ module Mongoid
133
136
  with_strategy(:__intersect__, criterion, operator)
134
137
  end
135
138
 
136
- # Adds the criterion to the existing selection.
139
+ # Adds $and/$or/$nor criteria to a copy of this selection.
140
+ #
141
+ # Each of the criteria can be a Hash of key/value pairs or MongoDB
142
+ # operators (keys beginning with $), or a Selectable object
143
+ # (which typically will be a Criteria instance).
137
144
  #
138
145
  # @api private
139
146
  #
140
147
  # @example Add the criterion.
141
148
  # mergeable.__multi__([ 1, 2 ], "$in")
142
149
  #
143
- # @param [ Hash ] criterion The criteria.
150
+ # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
151
+ # matches or Criteria objects.
144
152
  # @param [ String ] operator The MongoDB operator.
145
153
  #
146
154
  # @return [ Mergeable ] The new mergeable.
147
155
  #
148
156
  # @since 1.0.0
149
- def __multi__(criterion, operator)
157
+ def __multi__(criteria, operator)
150
158
  clone.tap do |query|
151
159
  sel = query.selector
152
- criterion.flatten.each do |expr|
160
+ criteria.flatten.each do |expr|
153
161
  next unless expr
154
- criteria = sel[operator] || []
155
- normalized = expr.inject({}) do |hash, (field, value)|
156
- hash.merge!(field.__expr_part__(value.__expand_complex__))
157
- hash
162
+ result_criteria = sel[operator] || []
163
+ if expr.is_a?(Selectable)
164
+ expr = expr.selector
158
165
  end
159
- sel.store(operator, criteria.push(normalized))
166
+ normalized = _mongoid_expand_keys(expr)
167
+ sel.store(operator, result_criteria.push(normalized))
160
168
  end
161
169
  end
162
170
  end
163
171
 
172
+ # Combines criteria into a MongoDB selector.
173
+ #
174
+ # Criteria is an array of criterions which will be flattened.
175
+ #
176
+ # Each criterion can be:
177
+ # - A hash
178
+ # - A Criteria instance
179
+ # - nil, in which case it is ignored
180
+ #
181
+ # @api private
182
+ private def _mongoid_add_top_level_operation(operator, criteria)
183
+ # Flatten the criteria. The idea is that predicates in MongoDB
184
+ # are always hashes and are never arrays. This method additionally
185
+ # allows Criteria instances as predicates.
186
+ # The flattening is existing Mongoid behavior but we could possibly
187
+ # get rid of it as applications can splat their predicates, or
188
+ # flatten if needed.
189
+ clone.tap do |query|
190
+ sel = query.selector
191
+ _mongoid_flatten_arrays(criteria).each do |criterion|
192
+ if criterion.is_a?(Selectable)
193
+ expr = _mongoid_expand_keys(criterion.selector)
194
+ else
195
+ expr = _mongoid_expand_keys(criterion)
196
+ end
197
+ if sel.empty?
198
+ sel.store(operator, [expr])
199
+ elsif sel.keys == [operator]
200
+ sel.store(operator, sel[operator] + [expr])
201
+ else
202
+ operands = [sel.dup] + [expr]
203
+ sel.clear
204
+ sel.store(operator, operands)
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ # Calling .flatten on an array which includes a Criteria instance
211
+ # evaluates the criteria, which we do not want. Hence this method
212
+ # explicitly only expands Array objects and Array subclasses.
213
+ private def _mongoid_flatten_arrays(array)
214
+ out = []
215
+ pending = array.dup
216
+ until pending.empty?
217
+ item = pending.shift
218
+ if item.nil?
219
+ # skip
220
+ elsif item.is_a?(Array)
221
+ pending += item
222
+ else
223
+ out << item
224
+ end
225
+ end
226
+ out
227
+ end
228
+
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 ] Criteria including Key instances.
241
+ #
242
+ # @return [ Hash ] 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
299
+ end
300
+ result
301
+ end
302
+
164
303
  # Adds the criterion to the existing selection.
165
304
  #
166
305
  # @api private
@@ -175,6 +314,9 @@ module Mongoid
175
314
  #
176
315
  # @since 1.0.0
177
316
  def __override__(criterion, operator)
317
+ if criterion.is_a?(Selectable)
318
+ criterion = criterion.selector
319
+ end
178
320
  selection(criterion) do |selector, field, value|
179
321
  expression = prepare(field, operator, value)
180
322
  existing = selector[field]
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
5
7
 
6
- # The optional module includes all behaviour that has to do with extra
8
+ # The optional module includes all behavior that has to do with extra
7
9
  # options surrounding queries, like skip, limit, sorting, etc.
8
10
  module Optional
9
11
  extend Macroable
@@ -169,10 +171,10 @@ module Mongoid
169
171
  # optional.order_by([[ name, 1 ], [ dob, -1 ]])
170
172
  #
171
173
  # @example Add sorting options via an array with symbol directions.
172
- # optional.order_by([[ name, :asc ], [ dob, :desc ]])
174
+ # optional.order_by([[ :name, :asc ], [ :dob, :desc ]])
173
175
  #
174
176
  # @example Add sorting options via an array with string directions.
175
- # optional.order_by([[ name, "asc" ], [ dob, "desc" ]])
177
+ # optional.order_by([[ "name", "asc" ], [ "dob", "desc" ]])
176
178
  #
177
179
  # @example Add sorting options with keys.
178
180
  # optional.order_by(:name.asc, :dob.desc)
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
@@ -31,7 +33,7 @@ module Mongoid
31
33
  # Add a group operation to the aggregation pipeline.
32
34
  #
33
35
  # @example Add a group operation.
34
- # pipeline.group(:count.sum => 1, :max.max => "likes")
36
+ # pipeline.group(:_id => "foo", :count.sum => 1, :max.max => "likes")
35
37
  #
36
38
  # @param [ Hash ] entry The group entry.
37
39
  #
@@ -74,7 +76,8 @@ module Mongoid
74
76
  # pipeline.unwind(:field)
75
77
  # pipeline.unwind(document)
76
78
  #
77
- # @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.
78
81
  #
79
82
  # @return [ Pipeline ] The pipeline.
80
83
  #
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: utf-8
3
+
2
4
  module Mongoid
3
5
  class Criteria
4
6
  module Queryable
@@ -41,8 +43,32 @@ module Mongoid
41
43
  # @return [ Selectable ] The cloned selectable.
42
44
  #
43
45
  # @since 1.0.0
44
- def all(criterion = nil)
45
- send(strategy || :__union__, with_array_values(criterion), "$all")
46
+ def all(*criteria)
47
+ if criteria.empty?
48
+ return clone.tap do |query|
49
+ query.reset_strategies!
50
+ end
51
+ end
52
+
53
+ criteria.inject(clone) do |query, condition|
54
+ if condition.nil?
55
+ raise Errors::CriteriaArgumentRequired, :all
56
+ end
57
+
58
+ condition = expand_condition_to_array_values(condition)
59
+
60
+ if strategy
61
+ send(strategy, condition, "$all")
62
+ else
63
+ condition.inject(query) do |_query, (field, value)|
64
+ v = {'$all' => value}
65
+ if negating?
66
+ v = {'$not' => v}
67
+ end
68
+ _query.add_field_expression(field.to_s, v)
69
+ end
70
+ end
71
+ end.reset_strategies!
46
72
  end
47
73
  alias :all_in :all
48
74
  key :all, :union, "$all"
@@ -52,14 +78,44 @@ module Mongoid
52
78
  # @example Add the criterion.
53
79
  # selectable.and({ field: value }, { other: value })
54
80
  #
55
- # @param [ Array<Hash> ] criterion Multiple key/value pair matches that
56
- # all must match to return results.
81
+ # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
82
+ # matches or Criteria objects that all must match to return results.
57
83
  #
58
- # @return [ Selectable ] The cloned selectable.
84
+ # @return [ Selectable ] The new selectable.
59
85
  #
60
86
  # @since 1.0.0
61
- def and(*criterion)
62
- __multi__(criterion, "$and")
87
+ def and(*criteria)
88
+ _mongoid_flatten_arrays(criteria).inject(self.clone) do |c, new_s|
89
+ if new_s.is_a?(Selectable)
90
+ new_s = new_s.selector
91
+ end
92
+ normalized = _mongoid_expand_keys(new_s)
93
+ normalized.each do |k, v|
94
+ k = k.to_s
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
113
+ else
114
+ c.selector.store(k, v)
115
+ end
116
+ end
117
+ c
118
+ end
63
119
  end
64
120
  alias :all_of :and
65
121
 
@@ -76,7 +132,11 @@ module Mongoid
76
132
  # @return [ Selectable ] The cloned selectable.
77
133
  #
78
134
  # @since 1.0.0
79
- def between(criterion = nil)
135
+ def between(criterion)
136
+ if criterion.nil?
137
+ raise Errors::CriteriaArgumentRequired, :between
138
+ end
139
+
80
140
  selection(criterion) do |selector, field, value|
81
141
  selector.store(
82
142
  field,
@@ -104,7 +164,11 @@ module Mongoid
104
164
  # @return [ Selectable ] The cloned selectable.
105
165
  #
106
166
  # @since 1.0.0
107
- def elem_match(criterion = nil)
167
+ def elem_match(criterion)
168
+ if criterion.nil?
169
+ raise Errors::CriteriaArgumentRequired, :elem_match
170
+ end
171
+
108
172
  __override__(criterion, "$elemMatch")
109
173
  end
110
174
  key :elem_match, :override, "$elemMatch"
@@ -125,7 +189,11 @@ module Mongoid
125
189
  # @return [ Selectable ] The cloned selectable.
126
190
  #
127
191
  # @since 1.0.0
128
- def exists(criterion = nil)
192
+ def exists(criterion)
193
+ if criterion.nil?
194
+ raise Errors::CriteriaArgumentRequired, :exists
195
+ end
196
+
129
197
  typed_override(criterion, "$exists") do |value|
130
198
  ::Boolean.evolve(value)
131
199
  end
@@ -170,7 +238,11 @@ module Mongoid
170
238
  # @return [ Selectable ] The cloned selectable.
171
239
  #
172
240
  # @since 2.0.0
173
- def geo_spacial(criterion = nil)
241
+ def geo_spacial(criterion)
242
+ if criterion.nil?
243
+ raise Errors::CriteriaArgumentRequired, :geo_spacial
244
+ end
245
+
174
246
  __merge__(criterion)
175
247
  end
176
248
  key :intersects_line, :override, "$geoIntersects", "$geometry" do |value|
@@ -200,7 +272,11 @@ module Mongoid
200
272
  # @return [ Selectable ] The cloned selectable.
201
273
  #
202
274
  # @since 1.0.0
203
- def gt(criterion = nil)
275
+ def gt(criterion)
276
+ if criterion.nil?
277
+ raise Errors::CriteriaArgumentRequired, :gt
278
+ end
279
+
204
280
  __override__(criterion, "$gt")
205
281
  end
206
282
  key :gt, :override, "$gt"
@@ -218,7 +294,11 @@ module Mongoid
218
294
  # @return [ Selectable ] The cloned selectable.
219
295
  #
220
296
  # @since 1.0.0
221
- def gte(criterion = nil)
297
+ def gte(criterion)
298
+ if criterion.nil?
299
+ raise Errors::CriteriaArgumentRequired, :gte
300
+ end
301
+
222
302
  __override__(criterion, "$gte")
223
303
  end
224
304
  key :gte, :override, "$gte"
@@ -234,13 +314,29 @@ module Mongoid
234
314
  # @example Execute an $in in a where query.
235
315
  # selectable.where(:field.in => [ 1, 2, 3 ])
236
316
  #
237
- # @param [ Hash ] criterion The field/value criterion pairs.
317
+ # @param [ Hash ] condition The field/value criterion pairs.
238
318
  #
239
319
  # @return [ Selectable ] The cloned selectable.
240
320
  #
241
321
  # @since 1.0.0
242
- def in(criterion = nil)
243
- send(strategy || :__intersect__, with_array_values(criterion), "$in")
322
+ def in(condition)
323
+ if condition.nil?
324
+ raise Errors::CriteriaArgumentRequired, :in
325
+ end
326
+
327
+ condition = expand_condition_to_array_values(condition)
328
+
329
+ if strategy
330
+ send(strategy, condition, "$in")
331
+ else
332
+ condition.inject(clone) do |query, (field, value)|
333
+ v = {'$in' => value}
334
+ if negating?
335
+ v = {'$not' => v}
336
+ end
337
+ query.add_field_expression(field.to_s, v)
338
+ end.reset_strategies!
339
+ end
244
340
  end
245
341
  alias :any_in :in
246
342
  key :in, :intersect, "$in"
@@ -258,7 +354,11 @@ module Mongoid
258
354
  # @return [ Selectable ] The cloned selectable.
259
355
  #
260
356
  # @since 1.0.0
261
- def lt(criterion = nil)
357
+ def lt(criterion)
358
+ if criterion.nil?
359
+ raise Errors::CriteriaArgumentRequired, :lt
360
+ end
361
+
262
362
  __override__(criterion, "$lt")
263
363
  end
264
364
  key :lt, :override, "$lt"
@@ -276,7 +376,11 @@ module Mongoid
276
376
  # @return [ Selectable ] The cloned selectable.
277
377
  #
278
378
  # @since 1.0.0
279
- def lte(criterion = nil)
379
+ def lte(criterion)
380
+ if criterion.nil?
381
+ raise Errors::CriteriaArgumentRequired, :lte
382
+ end
383
+
280
384
  __override__(criterion, "$lte")
281
385
  end
282
386
  key :lte, :override, "$lte"
@@ -291,7 +395,12 @@ module Mongoid
291
395
  # @return [ Selectable ] The cloned selectable.
292
396
  #
293
397
  # @since 1.0.0
294
- def max_distance(criterion = nil)
398
+ def max_distance(criterion)
399
+ if criterion.nil?
400
+ raise Errors::CriteriaArgumentRequired, :max_distance
401
+ end
402
+
403
+ # $maxDistance must be given together with $near
295
404
  __add__(criterion, "$maxDistance")
296
405
  end
297
406
 
@@ -308,7 +417,11 @@ module Mongoid
308
417
  # @return [ Selectable ] The cloned selectable.
309
418
  #
310
419
  # @since 1.0.0
311
- def mod(criterion = nil)
420
+ def mod(criterion)
421
+ if criterion.nil?
422
+ raise Errors::CriteriaArgumentRequired, :mod
423
+ end
424
+
312
425
  __override__(criterion, "$mod")
313
426
  end
314
427
  key :mod, :override, "$mod"
@@ -326,7 +439,11 @@ module Mongoid
326
439
  # @return [ Selectable ] The cloned selectable.
327
440
  #
328
441
  # @since 1.0.0
329
- def ne(criterion = nil)
442
+ def ne(criterion)
443
+ if criterion.nil?
444
+ raise Errors::CriteriaArgumentRequired, :ne
445
+ end
446
+
330
447
  __override__(criterion, "$ne")
331
448
  end
332
449
  alias :excludes :ne
@@ -345,7 +462,11 @@ module Mongoid
345
462
  # @return [ Selectable ] The cloned selectable.
346
463
  #
347
464
  # @since 1.0.0
348
- def near(criterion = nil)
465
+ def near(criterion)
466
+ if criterion.nil?
467
+ raise Errors::CriteriaArgumentRequired, :near
468
+ end
469
+
349
470
  __override__(criterion, "$near")
350
471
  end
351
472
  key :near, :override, "$near"
@@ -363,7 +484,11 @@ module Mongoid
363
484
  # @return [ Selectable ] The cloned selectable.
364
485
  #
365
486
  # @since 1.0.0
366
- def near_sphere(criterion = nil)
487
+ def near_sphere(criterion)
488
+ if criterion.nil?
489
+ raise Errors::CriteriaArgumentRequired, :near_sphere
490
+ end
491
+
367
492
  __override__(criterion, "$nearSphere")
368
493
  end
369
494
  key :near_sphere, :override, "$nearSphere"
@@ -379,13 +504,29 @@ module Mongoid
379
504
  # @example Execute an $nin in a where query.
380
505
  # selectable.where(:field.nin => [ 1, 2, 3 ])
381
506
  #
382
- # @param [ Hash ] criterion The field/value criterion pairs.
507
+ # @param [ Hash ] condition The field/value criterion pairs.
383
508
  #
384
509
  # @return [ Selectable ] The cloned selectable.
385
510
  #
386
511
  # @since 1.0.0
387
- def nin(criterion = nil)
388
- send(strategy || :__intersect__, with_array_values(criterion), "$nin")
512
+ def nin(condition)
513
+ if condition.nil?
514
+ raise Errors::CriteriaArgumentRequired, :nin
515
+ end
516
+
517
+ condition = expand_condition_to_array_values(condition)
518
+
519
+ if strategy
520
+ send(strategy, condition, "$nin")
521
+ else
522
+ condition.inject(clone) do |query, (field, value)|
523
+ v = {'$nin' => value}
524
+ if negating?
525
+ v = {'$not' => v}
526
+ end
527
+ query.add_field_expression(field.to_s, v)
528
+ end.reset_strategies!
529
+ end
389
530
  end
390
531
  alias :not_in :nin
391
532
  key :nin, :intersect, "$nin"
@@ -395,13 +536,14 @@ module Mongoid
395
536
  # @example Add the $nor selection.
396
537
  # selectable.nor(field: 1, field: 2)
397
538
  #
398
- # @param [ Array ] criterion An array of hash criterion.
539
+ # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
540
+ # matches or Criteria objects.
399
541
  #
400
- # @return [ Selectable ] The cloned selectable.
542
+ # @return [ Selectable ] The new selectable.
401
543
  #
402
544
  # @since 1.0.0
403
- def nor(*criterion)
404
- __multi__(criterion, "$nor")
545
+ def nor(*criteria)
546
+ _mongoid_add_top_level_operation('$nor', criteria)
405
547
  end
406
548
 
407
549
  # Is the current selectable negating the next selection?
@@ -416,9 +558,9 @@ module Mongoid
416
558
  !!negating
417
559
  end
418
560
 
419
- # Negate the next selection.
561
+ # Negate the arguments, or the next selection if no arguments are given.
420
562
  #
421
- # @example Negate the selection.
563
+ # @example Negate the next selection.
422
564
  # selectable.not.in(field: [ 1, 2 ])
423
565
  #
424
566
  # @example Add the $not criterion.
@@ -427,34 +569,145 @@ module Mongoid
427
569
  # @example Execute a $not in a where query.
428
570
  # selectable.where(:field.not => /Bob/)
429
571
  #
430
- # @param [ Hash ] criterion The field/value pairs to negate.
572
+ # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
573
+ # matches or Criteria objects to negate.
431
574
  #
432
- # @return [ Selectable ] The negated selectable.
575
+ # @return [ Selectable ] The new selectable.
433
576
  #
434
577
  # @since 1.0.0
435
- def not(*criterion)
436
- if criterion.empty?
578
+ def not(*criteria)
579
+ if criteria.empty?
437
580
  dup.tap { |query| query.negating = true }
438
581
  else
439
- __override__(criterion.first, "$not")
582
+ criteria.compact.inject(self.clone) do |c, new_s|
583
+ if new_s.is_a?(Selectable)
584
+ new_s = new_s.selector
585
+ end
586
+ _mongoid_expand_keys(new_s).each do |k, v|
587
+ k = k.to_s
588
+ if c.selector[k] || k[0] == ?$
589
+ c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
590
+ else
591
+ if v.is_a?(Hash)
592
+ c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
593
+ else
594
+ if v.is_a?(Regexp)
595
+ negated_operator = '$not'
596
+ else
597
+ negated_operator = '$ne'
598
+ end
599
+ c = c.send(:__override__, {k => v}, negated_operator)
600
+ end
601
+ end
602
+ end
603
+ c
604
+ end
440
605
  end
441
606
  end
442
607
  key :not, :override, "$not"
443
608
 
444
- # Adds $or selection to the selectable.
609
+ # Creates a disjunction using $or from the existing criteria in the
610
+ # receiver and the provided arguments.
611
+ #
612
+ # This behavior (receiver becoming one of the disjunction operands)
613
+ # matches ActiveRecord's +or+ behavior.
614
+ #
615
+ # Use +any_of+ to add a disjunction of the arguments as an additional
616
+ # constraint to the criteria already existing in the receiver.
617
+ #
618
+ # Each argument can be a Hash, a Criteria object, an array of
619
+ # Hash or Criteria objects, or a nested array. Nested arrays will be
620
+ # flattened and can be of any depth. Passing arrays is deprecated.
445
621
  #
446
- # @example Add the $or selection.
622
+ # @example Add the $or selection where both fields must have the specified values.
447
623
  # selectable.or(field: 1, field: 2)
448
624
  #
449
- # @param [ Array ] criterion An array of hash criterion.
625
+ # @example Add the $or selection where either value match is sufficient.
626
+ # selectable.or({field: 1}, {field: 2})
450
627
  #
451
- # @return [ Selectable ] The cloned selectable.
628
+ # @example Same as previous example but using the deprecated array wrap.
629
+ # selectable.or([{field: 1}, {field: 2}])
630
+ #
631
+ # @example Same as previous example, also deprecated.
632
+ # selectable.or([{field: 1}], [{field: 2}])
633
+ #
634
+ # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
635
+ # Multiple key/value pair matches or Criteria objects, or arrays
636
+ # thereof. Passing arrays is deprecated.
637
+ #
638
+ # @return [ Selectable ] The new selectable.
639
+ #
640
+ # @since 1.0.0
641
+ def or(*criteria)
642
+ _mongoid_add_top_level_operation('$or', criteria)
643
+ end
644
+
645
+ # Adds a disjunction of the arguments as an additional constraint
646
+ # to the criteria already existing in the receiver.
647
+ #
648
+ # Use +or+ to make the receiver one of the disjunction operands.
649
+ #
650
+ # Each argument can be a Hash, a Criteria object, an array of
651
+ # Hash or Criteria objects, or a nested array. Nested arrays will be
652
+ # flattened and can be of any depth. Passing arrays is deprecated.
653
+ #
654
+ # @example Add the $or selection where both fields must have the specified values.
655
+ # selectable.any_of(field: 1, field: 2)
656
+ #
657
+ # @example Add the $or selection where either value match is sufficient.
658
+ # selectable.any_of({field: 1}, {field: 2})
659
+ #
660
+ # @example Same as previous example but using the deprecated array wrap.
661
+ # selectable.any_of([{field: 1}, {field: 2}])
662
+ #
663
+ # @example Same as previous example, also deprecated.
664
+ # selectable.any_of([{field: 1}], [{field: 2}])
665
+ #
666
+ # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
667
+ # Multiple key/value pair matches or Criteria objects, or arrays
668
+ # thereof. Passing arrays is deprecated.
669
+ #
670
+ # @return [ Selectable ] The new selectable.
452
671
  #
453
672
  # @since 1.0.0
454
- def or(*criterion)
455
- __multi__(criterion, "$or")
673
+ def any_of(*criteria)
674
+ criteria = _mongoid_flatten_arrays(criteria)
675
+ case criteria.length
676
+ when 0
677
+ clone
678
+ when 1
679
+ # When we have a single criteria, any_of behaves like and.
680
+ # Note: criteria can be a Query object, which #where method does
681
+ # not support.
682
+ self.and(*criteria)
683
+ else
684
+ # When we have multiple criteria, combine them all with $or
685
+ # and add the result to self.
686
+ exprs = criteria.map do |criterion|
687
+ if criterion.is_a?(Selectable)
688
+ _mongoid_expand_keys(criterion.selector)
689
+ else
690
+ Hash[criterion.map do |k, v|
691
+ if k.is_a?(Symbol)
692
+ [k.to_s, v]
693
+ else
694
+ [k, v]
695
+ end
696
+ end]
697
+ end
698
+ end
699
+ # Should be able to do:
700
+ #where('$or' => exprs)
701
+ # But since that is broken do instead:
702
+ clone.tap do |query|
703
+ if query.selector['$or']
704
+ query.selector.store('$or', query.selector['$or'] + exprs)
705
+ else
706
+ query.selector.store('$or', exprs)
707
+ end
708
+ end
709
+ end
456
710
  end
457
- alias :any_of :or
458
711
 
459
712
  # Add a $size selection for array fields.
460
713
  #
@@ -472,7 +725,11 @@ module Mongoid
472
725
  # @return [ Selectable ] The cloned selectable.
473
726
  #
474
727
  # @since 1.0.0
475
- def with_size(criterion = nil)
728
+ def with_size(criterion)
729
+ if criterion.nil?
730
+ raise Errors::CriteriaArgumentRequired, :with_size
731
+ end
732
+
476
733
  typed_override(criterion, "$size") do |value|
477
734
  ::Integer.evolve(value)
478
735
  end
@@ -496,7 +753,11 @@ module Mongoid
496
753
  # @return [ Selectable ] The cloned selectable.
497
754
  #
498
755
  # @since 1.0.0
499
- def with_type(criterion = nil)
756
+ def with_type(criterion)
757
+ if criterion.nil?
758
+ raise Errors::CriteriaArgumentRequired, :with_type
759
+ end
760
+
500
761
  typed_override(criterion, "$type") do |value|
501
762
  ::Integer.evolve(value)
502
763
  end
@@ -527,21 +788,23 @@ module Mongoid
527
788
  #
528
789
  # @since 2.2.0
529
790
  def text_search(terms, opts = nil)
791
+ if terms.nil?
792
+ raise Errors::CriteriaArgumentRequired, :terms
793
+ end
794
+
530
795
  clone.tap do |query|
531
- if terms
532
- criterion = {'$text' => { '$search' => terms }}
533
- criterion['$text'].merge!(opts) if opts
534
- if query.selector['$text']
535
- # Per https://docs.mongodb.com/manual/reference/operator/query/text/
536
- # multiple $text expressions are not currently supported by
537
- # MongoDB server, but build the query correctly instead of
538
- # overwriting previous text search condition with the currently
539
- # given one.
540
- Mongoid.logger.warn('Multiple $text expressions per query are not currently supported by the server')
541
- query.selector = {'$and' => [query.selector]}.merge(criterion)
542
- else
543
- query.selector = query.selector.merge(criterion)
544
- end
796
+ criterion = {'$text' => { '$search' => terms }}
797
+ criterion['$text'].merge!(opts) if opts
798
+ if query.selector['$text']
799
+ # Per https://docs.mongodb.com/manual/reference/operator/query/text/
800
+ # multiple $text expressions are not currently supported by
801
+ # MongoDB server, but build the query correctly instead of
802
+ # overwriting previous text search condition with the currently
803
+ # given one.
804
+ Mongoid.logger.warn('Multiple $text expressions per query are not currently supported by the server')
805
+ query.selector = {'$and' => [query.selector]}.merge(criterion)
806
+ else
807
+ query.selector = query.selector.merge(criterion)
545
808
  end
546
809
  end
547
810
  end
@@ -561,18 +824,38 @@ module Mongoid
561
824
  # @return [ Selectable ] The cloned selectable.
562
825
  #
563
826
  # @since 1.0.0
564
- def where(criterion = nil)
565
- # We need to save the criterion in an instance variable so Modifiable methods
566
- # know how to create a polymorphic object.
567
- @criterion = criterion
568
- criterion.is_a?(String) ? js_query(criterion) : expr_query(criterion)
827
+ def where(*criteria)
828
+ criteria.inject(clone) do |query, criterion|
829
+ if criterion.nil?
830
+ raise Errors::CriteriaArgumentRequired, :where
831
+ end
832
+
833
+ # We need to save the criterion in an instance variable so
834
+ # Modifiable methods know how to create a polymorphic object.
835
+ # Note that this method in principle accepts multiple criteria,
836
+ # but only the first one will be stored in @criterion. This
837
+ # works out to be fine because first_or_create etc. methods
838
+ # only ever specify one criterion to #where.
839
+ @criterion = criterion
840
+ if criterion.is_a?(String)
841
+ js_query(criterion)
842
+ else
843
+ expr_query(criterion)
844
+ end
845
+ end.reset_strategies!
569
846
  end
570
847
 
571
848
  private
572
849
 
573
- # Create the standard expression query.
850
+ # Adds the specified expression to the query.
574
851
  #
575
- # @api private
852
+ # Criterion must be a hash in one of the following forms:
853
+ # - {field_name: value}
854
+ # - {'field_name' => value}
855
+ # - {key_instance: value}
856
+ # - {'$operator' => operator_value_expression}
857
+ #
858
+ # Field name and operator may be given as either strings or symbols.
576
859
  #
577
860
  # @example Create the selection.
578
861
  # selectable.expr_query(age: 50)
@@ -582,9 +865,24 @@ module Mongoid
582
865
  # @return [ Selectable ] The cloned selectable.
583
866
  #
584
867
  # @since 1.0.0
868
+ # @api private
585
869
  def expr_query(criterion)
586
- selection(criterion) do |selector, field, value|
587
- selector.merge!(field.__expr_part__(value.__expand_complex__, negating?))
870
+ if criterion.nil?
871
+ raise ArgumentError, 'Criterion cannot be nil here'
872
+ end
873
+
874
+ clone.tap do |query|
875
+ criterion.each do |field, value|
876
+ field_s = field.to_s
877
+ if field_s[0] == ?$
878
+ # Query expression-level operator, like $and or $where
879
+ query.add_operator_expression(field_s, value)
880
+ else
881
+ exp_field, exp_value = expand_one_condition(field, value)
882
+ query.add_field_expression(exp_field, exp_value)
883
+ end
884
+ end
885
+ query.reset_strategies!
588
886
  end
589
887
  end
590
888
 
@@ -623,7 +921,13 @@ module Mongoid
623
921
  # @since 1.0.0
624
922
  def js_query(criterion)
625
923
  clone.tap do |query|
626
- query.selector.merge!("$where" => criterion)
924
+ if negating?
925
+ query.add_operator_expression('$and',
926
+ [{'$nor' => [{'$where' => criterion}]}])
927
+ else
928
+ query.add_operator_expression('$where', criterion)
929
+ end
930
+ query.reset_strategies!
627
931
  end
628
932
  end
629
933
 
@@ -650,26 +954,6 @@ module Mongoid
650
954
  end
651
955
  end
652
956
 
653
- # Convert the criterion values to $in friendly values. This means you,
654
- # array.
655
- #
656
- # @api private
657
- #
658
- # @example Convert all the values to arrays.
659
- # selectable.with_array_values({ key: 1...4 })
660
- #
661
- # @param [ Hash ] criterion The criterion.
662
- #
663
- # @return [ Hash ] The $in friendly criterion (array values).
664
- #
665
- # @since 1.0.0
666
- def with_array_values(criterion)
667
- return nil unless criterion
668
- criterion.each_pair do |key, value|
669
- criterion[key] = value.__array__
670
- end
671
- end
672
-
673
957
  class << self
674
958
 
675
959
  # Get the methods on the selectable that can be forwarded to from a model.