mongoid 7.1.11 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +10 -3
  4. data/lib/config/locales/en.yml +37 -14
  5. data/lib/mongoid/association/depending.rb +1 -6
  6. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +1 -1
  7. data/lib/mongoid/association/many.rb +3 -3
  8. data/lib/mongoid/association/proxy.rb +1 -1
  9. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  10. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  11. data/lib/mongoid/association/referenced/has_many/enumerable.rb +37 -2
  12. data/lib/mongoid/association/referenced/has_many/proxy.rb +9 -2
  13. data/lib/mongoid/association/referenced/has_one/buildable.rb +9 -1
  14. data/lib/mongoid/atomic/modifiers.rb +1 -1
  15. data/lib/mongoid/attributes/dynamic.rb +1 -1
  16. data/lib/mongoid/attributes.rb +1 -8
  17. data/lib/mongoid/clients/factory.rb +17 -0
  18. data/lib/mongoid/composable.rb +1 -0
  19. data/lib/mongoid/config/environment.rb +1 -9
  20. data/lib/mongoid/config.rb +3 -0
  21. data/lib/mongoid/contextual/atomic.rb +2 -7
  22. data/lib/mongoid/contextual/mongo.rb +23 -4
  23. data/lib/mongoid/contextual/none.rb +0 -3
  24. data/lib/mongoid/copyable.rb +7 -3
  25. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  26. data/lib/mongoid/criteria/queryable/mergeable.rb +2 -2
  27. data/lib/mongoid/criteria/queryable/selectable.rb +23 -8
  28. data/lib/mongoid/criteria/queryable/selector.rb +7 -3
  29. data/lib/mongoid/criteria/queryable/storable.rb +7 -7
  30. data/lib/mongoid/criteria.rb +58 -8
  31. data/lib/mongoid/document.rb +19 -9
  32. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +25 -0
  33. data/lib/mongoid/errors/invalid_elem_match_operator.rb +33 -0
  34. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +26 -0
  35. data/lib/mongoid/errors/invalid_expression_operator.rb +28 -0
  36. data/lib/mongoid/errors/invalid_field_operator.rb +33 -0
  37. data/lib/mongoid/errors/invalid_query.rb +41 -0
  38. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  39. data/lib/mongoid/errors.rb +7 -2
  40. data/lib/mongoid/extensions.rb +1 -0
  41. data/lib/mongoid/factory.rb +27 -10
  42. data/lib/mongoid/fields/validators/macro.rb +22 -9
  43. data/lib/mongoid/fields.rb +3 -0
  44. data/lib/mongoid/findable.rb +50 -14
  45. data/lib/mongoid/indexable.rb +2 -2
  46. data/lib/mongoid/interceptable.rb +2 -4
  47. data/lib/mongoid/matchable.rb +1 -149
  48. data/lib/mongoid/matcher/all.rb +22 -0
  49. data/lib/mongoid/matcher/and.rb +21 -0
  50. data/lib/mongoid/matcher/elem_match.rb +35 -0
  51. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  52. data/lib/mongoid/matcher/eq.rb +11 -0
  53. data/lib/mongoid/matcher/eq_impl.rb +32 -0
  54. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +21 -0
  55. data/lib/mongoid/matcher/exists.rb +15 -0
  56. data/lib/mongoid/matcher/expression.rb +40 -0
  57. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  58. data/lib/mongoid/matcher/field_expression.rb +63 -0
  59. data/lib/mongoid/matcher/field_operator.rb +52 -0
  60. data/lib/mongoid/matcher/gt.rb +17 -0
  61. data/lib/mongoid/matcher/gte.rb +17 -0
  62. data/lib/mongoid/matcher/in.rb +25 -0
  63. data/lib/mongoid/matcher/lt.rb +17 -0
  64. data/lib/mongoid/matcher/lte.rb +17 -0
  65. data/lib/mongoid/matcher/ne.rb +16 -0
  66. data/lib/mongoid/matcher/nin.rb +11 -0
  67. data/lib/mongoid/matcher/nor.rb +25 -0
  68. data/lib/mongoid/matcher/not.rb +29 -0
  69. data/lib/mongoid/matcher/or.rb +21 -0
  70. data/lib/mongoid/matcher/regex.rb +41 -0
  71. data/lib/mongoid/matcher/size.rb +26 -0
  72. data/lib/mongoid/matcher.rb +127 -0
  73. data/lib/mongoid/persistable/deletable.rb +1 -1
  74. data/lib/mongoid/persistence_context.rb +1 -3
  75. data/lib/mongoid/query_cache.rb +64 -62
  76. data/lib/mongoid/reloadable.rb +2 -7
  77. data/lib/mongoid/serializable.rb +1 -1
  78. data/lib/mongoid/stringified_symbol.rb +53 -0
  79. data/lib/mongoid/tasks/database.rb +1 -1
  80. data/lib/mongoid/traversable.rb +111 -4
  81. data/lib/mongoid/validatable/associated.rb +1 -1
  82. data/lib/mongoid/validatable/presence.rb +3 -3
  83. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  84. data/lib/mongoid/version.rb +1 -1
  85. data/lib/mongoid.rb +23 -1
  86. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -8
  87. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
  88. data/spec/README.md +19 -4
  89. data/spec/integration/app_spec.rb +84 -174
  90. data/spec/integration/associations/embedded_spec.rb +94 -0
  91. data/spec/integration/associations/has_many_spec.rb +67 -14
  92. data/spec/integration/associations/has_one_spec.rb +67 -14
  93. data/spec/integration/associations/nested_attributes_assignment_spec.rb +116 -0
  94. data/spec/integration/atomic/modifiers_spec.rb +117 -0
  95. data/spec/integration/discriminator_key_spec.rb +354 -0
  96. data/spec/integration/discriminator_value_spec.rb +207 -0
  97. data/spec/integration/document_spec.rb +0 -21
  98. data/spec/integration/{matchable_spec.rb → matcher_examples_spec.rb} +120 -41
  99. data/spec/integration/matcher_operator_data/all.yml +140 -0
  100. data/spec/integration/matcher_operator_data/and.yml +93 -0
  101. data/spec/integration/matcher_operator_data/elem_match.yml +363 -0
  102. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  103. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  104. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  105. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  106. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  107. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  108. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  109. data/spec/integration/matcher_operator_data/implicit_traversal.yml +16 -0
  110. data/spec/integration/matcher_operator_data/in.yml +194 -0
  111. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  112. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  113. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  114. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  115. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  116. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  117. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  118. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  119. data/spec/integration/matcher_operator_data/not.yml +196 -0
  120. data/spec/integration/matcher_operator_data/or.yml +137 -0
  121. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  122. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  123. data/spec/integration/matcher_operator_data/size.yml +174 -0
  124. data/spec/integration/matcher_operator_spec.rb +100 -0
  125. data/spec/integration/matcher_spec.rb +189 -0
  126. data/spec/integration/server_query_spec.rb +142 -0
  127. data/spec/integration/stringified_symbol_field_spec.rb +190 -0
  128. data/spec/lite_spec_helper.rb +4 -3
  129. data/spec/mongoid/association/depending_spec.rb +78 -26
  130. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +0 -50
  131. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +37 -17
  132. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  133. data/spec/mongoid/association/embedded/embeds_one_models.rb +1 -0
  134. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +0 -17
  135. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +460 -186
  136. data/spec/mongoid/association/referenced/has_many_models.rb +21 -0
  137. data/spec/mongoid/association/referenced/has_one_models.rb +21 -0
  138. data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
  139. data/spec/mongoid/atomic/modifiers_spec.rb +47 -0
  140. data/spec/mongoid/atomic/paths_spec.rb +0 -41
  141. data/spec/mongoid/atomic_spec.rb +23 -0
  142. data/spec/mongoid/attributes/nested_spec.rb +1 -1
  143. data/spec/mongoid/attributes_spec.rb +0 -241
  144. data/spec/mongoid/clients/factory_spec.rb +35 -9
  145. data/spec/mongoid/clients/options_spec.rb +3 -11
  146. data/spec/mongoid/clients/sessions_spec.rb +1 -6
  147. data/spec/mongoid/config/environment_spec.rb +8 -86
  148. data/spec/mongoid/config_spec.rb +28 -0
  149. data/spec/mongoid/contextual/atomic_spec.rb +29 -81
  150. data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
  151. data/spec/mongoid/contextual/mongo_spec.rb +70 -16
  152. data/spec/mongoid/copyable_spec.rb +197 -18
  153. data/spec/mongoid/copyable_spec_models.rb +28 -0
  154. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +0 -36
  155. data/spec/mongoid/criteria/queryable/selectable_spec.rb +84 -82
  156. data/spec/mongoid/criteria_spec.rb +204 -43
  157. data/spec/mongoid/document_query_spec.rb +0 -51
  158. data/spec/mongoid/document_spec.rb +90 -36
  159. data/spec/mongoid/equality_spec.rb +0 -1
  160. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  161. data/spec/mongoid/errors/mongoid_error_spec.rb +8 -20
  162. data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
  163. data/spec/mongoid/factory_spec.rb +261 -28
  164. data/spec/mongoid/fields_spec.rb +48 -2
  165. data/spec/mongoid/findable_spec.rb +32 -0
  166. data/spec/mongoid/indexable_spec.rb +28 -2
  167. data/spec/mongoid/inspectable_spec.rb +29 -2
  168. data/spec/mongoid/interceptable_spec.rb +2 -2
  169. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +259 -0
  170. data/spec/mongoid/matcher/extract_attribute_spec.rb +47 -0
  171. data/spec/mongoid/persistable/creatable_spec.rb +108 -25
  172. data/spec/mongoid/persistable/deletable_spec.rb +86 -0
  173. data/spec/mongoid/persistable/savable_spec.rb +174 -16
  174. data/spec/mongoid/persistable/settable_spec.rb +0 -30
  175. data/spec/mongoid/persistable/updatable_spec.rb +0 -2
  176. data/spec/mongoid/persistable_spec.rb +2 -2
  177. data/spec/mongoid/query_cache_middleware_spec.rb +16 -3
  178. data/spec/mongoid/query_cache_spec.rb +442 -41
  179. data/spec/mongoid/reloadable_spec.rb +72 -0
  180. data/spec/mongoid/serializable_spec.rb +21 -3
  181. data/spec/mongoid/traversable_spec.rb +1100 -0
  182. data/spec/shared/lib/mrss/constraints.rb +10 -92
  183. data/spec/shared/lib/mrss/lite_constraints.rb +0 -16
  184. data/spec/shared/lib/mrss/spec_organizer.rb +2 -32
  185. data/spec/spec_helper.rb +3 -3
  186. data/spec/support/constraints.rb +24 -0
  187. data/spec/support/helpers.rb +1 -1
  188. data/spec/{app → support}/models/actor.rb +1 -1
  189. data/spec/{app → support}/models/address.rb +0 -4
  190. data/spec/support/models/armrest.rb +10 -0
  191. data/spec/{app → support}/models/browser.rb +1 -1
  192. data/spec/{app → support}/models/canvas.rb +1 -1
  193. data/spec/{app → support}/models/coding.rb +1 -1
  194. data/spec/support/models/crate.rb +13 -0
  195. data/spec/support/models/deed.rb +8 -0
  196. data/spec/{app → support}/models/dictionary.rb +0 -6
  197. data/spec/{app → support}/models/driver.rb +1 -1
  198. data/spec/support/models/guitar.rb +5 -0
  199. data/spec/support/models/idnodef.rb +8 -0
  200. data/spec/support/models/instrument.rb +9 -0
  201. data/spec/{app → support}/models/item.rb +1 -1
  202. data/spec/{app → support}/models/mop.rb +0 -10
  203. data/spec/support/models/order.rb +11 -0
  204. data/spec/{app → support}/models/owner.rb +2 -0
  205. data/spec/{app → support}/models/palette.rb +1 -1
  206. data/spec/{app → support}/models/person.rb +1 -10
  207. data/spec/support/models/piano.rb +5 -0
  208. data/spec/support/models/profile.rb +18 -0
  209. data/spec/support/models/publication.rb +5 -0
  210. data/spec/{app/models/profile.rb → support/models/scribe.rb} +2 -2
  211. data/spec/support/models/seat.rb +25 -0
  212. data/spec/{app → support}/models/shape.rb +2 -2
  213. data/spec/support/models/system_role.rb +7 -0
  214. data/spec/{app → support}/models/tool.rb +2 -2
  215. data/spec/support/models/toy.rb +10 -0
  216. data/spec/{app → support}/models/truck.rb +2 -0
  217. data/spec/{app → support}/models/vehicle.rb +7 -2
  218. data/spec/{app → support}/models/writer.rb +2 -2
  219. data/spec/support/spec_config.rb +1 -9
  220. data.tar.gz.sig +0 -0
  221. metadata +839 -820
  222. metadata.gz.sig +2 -2
  223. data/lib/mongoid/errors/empty_config_file.rb +0 -26
  224. data/lib/mongoid/errors/invalid_config_file.rb +0 -26
  225. data/lib/mongoid/matchable/all.rb +0 -30
  226. data/lib/mongoid/matchable/and.rb +0 -32
  227. data/lib/mongoid/matchable/default.rb +0 -121
  228. data/lib/mongoid/matchable/elem_match.rb +0 -36
  229. data/lib/mongoid/matchable/eq.rb +0 -23
  230. data/lib/mongoid/matchable/exists.rb +0 -25
  231. data/lib/mongoid/matchable/gt.rb +0 -25
  232. data/lib/mongoid/matchable/gte.rb +0 -25
  233. data/lib/mongoid/matchable/in.rb +0 -26
  234. data/lib/mongoid/matchable/lt.rb +0 -25
  235. data/lib/mongoid/matchable/lte.rb +0 -25
  236. data/lib/mongoid/matchable/ne.rb +0 -23
  237. data/lib/mongoid/matchable/nin.rb +0 -24
  238. data/lib/mongoid/matchable/nor.rb +0 -38
  239. data/lib/mongoid/matchable/or.rb +0 -35
  240. data/lib/mongoid/matchable/regexp.rb +0 -30
  241. data/lib/mongoid/matchable/size.rb +0 -23
  242. data/spec/app/models/customer.rb +0 -11
  243. data/spec/app/models/customer_address.rb +0 -12
  244. data/spec/app/models/publication.rb +0 -5
  245. data/spec/integration/callbacks_models.rb +0 -49
  246. data/spec/integration/callbacks_spec.rb +0 -216
  247. data/spec/integration/contextual/empty_spec.rb +0 -142
  248. data/spec/mongoid/errors/invalid_config_file_spec.rb +0 -32
  249. data/spec/mongoid/matchable/all_spec.rb +0 -34
  250. data/spec/mongoid/matchable/and_spec.rb +0 -190
  251. data/spec/mongoid/matchable/default_spec.rb +0 -140
  252. data/spec/mongoid/matchable/elem_match_spec.rb +0 -109
  253. data/spec/mongoid/matchable/eq_spec.rb +0 -49
  254. data/spec/mongoid/matchable/exists_spec.rb +0 -60
  255. data/spec/mongoid/matchable/gt_spec.rb +0 -89
  256. data/spec/mongoid/matchable/gte_spec.rb +0 -87
  257. data/spec/mongoid/matchable/in_spec.rb +0 -52
  258. data/spec/mongoid/matchable/lt_spec.rb +0 -88
  259. data/spec/mongoid/matchable/lte_spec.rb +0 -88
  260. data/spec/mongoid/matchable/ne_spec.rb +0 -49
  261. data/spec/mongoid/matchable/nin_spec.rb +0 -51
  262. data/spec/mongoid/matchable/nor_spec.rb +0 -210
  263. data/spec/mongoid/matchable/or_spec.rb +0 -134
  264. data/spec/mongoid/matchable/regexp_spec.rb +0 -62
  265. data/spec/mongoid/matchable/size_spec.rb +0 -28
  266. data/spec/mongoid/matchable_spec.rb +0 -856
  267. data/spec/shared/bin/get-mongodb-download-url +0 -17
  268. data/spec/shared/bin/s3-copy +0 -45
  269. data/spec/shared/bin/s3-upload +0 -69
  270. data/spec/shared/lib/mrss/cluster_config.rb +0 -226
  271. data/spec/shared/lib/mrss/docker_runner.rb +0 -271
  272. data/spec/shared/lib/mrss/event_subscriber.rb +0 -200
  273. data/spec/shared/lib/mrss/server_version_registry.rb +0 -120
  274. data/spec/shared/lib/mrss/utils.rb +0 -15
  275. data/spec/shared/share/Dockerfile.erb +0 -323
  276. data/spec/shared/share/haproxy-1.conf +0 -16
  277. data/spec/shared/share/haproxy-2.conf +0 -17
  278. data/spec/shared/shlib/distro.sh +0 -73
  279. data/spec/shared/shlib/server.sh +0 -367
  280. data/spec/shared/shlib/set_env.sh +0 -131
  281. /data/spec/{app → support}/models/account.rb +0 -0
  282. /data/spec/{app → support}/models/acolyte.rb +0 -0
  283. /data/spec/{app → support}/models/actress.rb +0 -0
  284. /data/spec/{app → support}/models/address_component.rb +0 -0
  285. /data/spec/{app → support}/models/address_number.rb +0 -0
  286. /data/spec/{app → support}/models/agency.rb +0 -0
  287. /data/spec/{app → support}/models/agent.rb +0 -0
  288. /data/spec/{app → support}/models/album.rb +0 -0
  289. /data/spec/{app → support}/models/alert.rb +0 -0
  290. /data/spec/{app → support}/models/animal.rb +0 -0
  291. /data/spec/{app → support}/models/answer.rb +0 -0
  292. /data/spec/{app → support}/models/appointment.rb +0 -0
  293. /data/spec/{app → support}/models/array_field.rb +0 -0
  294. /data/spec/{app → support}/models/article.rb +0 -0
  295. /data/spec/{app → support}/models/artist.rb +0 -0
  296. /data/spec/{app → support}/models/artwork.rb +0 -0
  297. /data/spec/{app → support}/models/audio.rb +0 -0
  298. /data/spec/{app → support}/models/augmentation.rb +0 -0
  299. /data/spec/{app → support}/models/author.rb +0 -0
  300. /data/spec/{app → support}/models/baby.rb +0 -0
  301. /data/spec/{app → support}/models/band.rb +0 -0
  302. /data/spec/{app → support}/models/bar.rb +0 -0
  303. /data/spec/{app → support}/models/basic.rb +0 -0
  304. /data/spec/{app → support}/models/bed.rb +0 -0
  305. /data/spec/{app → support}/models/big_palette.rb +0 -0
  306. /data/spec/{app → support}/models/birthday.rb +0 -0
  307. /data/spec/{app → support}/models/bomb.rb +0 -0
  308. /data/spec/{app → support}/models/book.rb +0 -0
  309. /data/spec/{app → support}/models/breed.rb +0 -0
  310. /data/spec/{app → support}/models/building.rb +0 -0
  311. /data/spec/{app → support}/models/building_address.rb +0 -0
  312. /data/spec/{app → support}/models/bus.rb +0 -0
  313. /data/spec/{app → support}/models/business.rb +0 -0
  314. /data/spec/{app → support}/models/callback_test.rb +0 -0
  315. /data/spec/{app → support}/models/car.rb +0 -0
  316. /data/spec/{app → support}/models/cat.rb +0 -0
  317. /data/spec/{app → support}/models/category.rb +0 -0
  318. /data/spec/{app → support}/models/child.rb +0 -0
  319. /data/spec/{app → support}/models/child_doc.rb +0 -0
  320. /data/spec/{app → support}/models/church.rb +0 -0
  321. /data/spec/{app → support}/models/circle.rb +0 -0
  322. /data/spec/{app → support}/models/circuit.rb +0 -0
  323. /data/spec/{app → support}/models/circus.rb +0 -0
  324. /data/spec/{app → support}/models/code.rb +0 -0
  325. /data/spec/{app → support}/models/coding/pull_request.rb +0 -0
  326. /data/spec/{app → support}/models/comment.rb +0 -0
  327. /data/spec/{app → support}/models/company.rb +0 -0
  328. /data/spec/{app → support}/models/consumption_period.rb +0 -0
  329. /data/spec/{app → support}/models/contextable_item.rb +0 -0
  330. /data/spec/{app → support}/models/contractor.rb +0 -0
  331. /data/spec/{app → support}/models/cookie.rb +0 -0
  332. /data/spec/{app → support}/models/country_code.rb +0 -0
  333. /data/spec/{app → support}/models/courier_job.rb +0 -0
  334. /data/spec/{app → support}/models/definition.rb +0 -0
  335. /data/spec/{app → support}/models/delegating_patient.rb +0 -0
  336. /data/spec/{app → support}/models/description.rb +0 -0
  337. /data/spec/{app → support}/models/division.rb +0 -0
  338. /data/spec/{app → support}/models/doctor.rb +0 -0
  339. /data/spec/{app → support}/models/dog.rb +0 -0
  340. /data/spec/{app → support}/models/dokument.rb +0 -0
  341. /data/spec/{app → support}/models/draft.rb +0 -0
  342. /data/spec/{app → support}/models/dragon.rb +0 -0
  343. /data/spec/{app → support}/models/drug.rb +0 -0
  344. /data/spec/{app → support}/models/dungeon.rb +0 -0
  345. /data/spec/{app → support}/models/edit.rb +0 -0
  346. /data/spec/{app → support}/models/email.rb +0 -0
  347. /data/spec/{app → support}/models/employer.rb +0 -0
  348. /data/spec/{app → support}/models/entry.rb +0 -0
  349. /data/spec/{app → support}/models/eraser.rb +0 -0
  350. /data/spec/{app → support}/models/even.rb +0 -0
  351. /data/spec/{app → support}/models/event.rb +0 -0
  352. /data/spec/{app → support}/models/exhibition.rb +0 -0
  353. /data/spec/{app → support}/models/exhibitor.rb +0 -0
  354. /data/spec/{app → support}/models/explosion.rb +0 -0
  355. /data/spec/{app → support}/models/eye.rb +0 -0
  356. /data/spec/{app → support}/models/eye_bowl.rb +0 -0
  357. /data/spec/{app → support}/models/face.rb +0 -0
  358. /data/spec/{app → support}/models/favorite.rb +0 -0
  359. /data/spec/{app → support}/models/filesystem.rb +0 -0
  360. /data/spec/{app → support}/models/fire_hydrant.rb +0 -0
  361. /data/spec/{app → support}/models/firefox.rb +0 -0
  362. /data/spec/{app → support}/models/fish.rb +0 -0
  363. /data/spec/{app → support}/models/folder.rb +0 -0
  364. /data/spec/{app → support}/models/folder_item.rb +0 -0
  365. /data/spec/{app → support}/models/fruits.rb +0 -0
  366. /data/spec/{app → support}/models/game.rb +0 -0
  367. /data/spec/{app → support}/models/ghost.rb +0 -0
  368. /data/spec/{app → support}/models/home.rb +0 -0
  369. /data/spec/{app → support}/models/house.rb +0 -0
  370. /data/spec/{app → support}/models/html_writer.rb +0 -0
  371. /data/spec/{app → support}/models/id_key.rb +0 -0
  372. /data/spec/{app → support}/models/image.rb +0 -0
  373. /data/spec/{app → support}/models/implant.rb +0 -0
  374. /data/spec/{app → support}/models/jar.rb +0 -0
  375. /data/spec/{app → support}/models/kaleidoscope.rb +0 -0
  376. /data/spec/{app → support}/models/kangaroo.rb +0 -0
  377. /data/spec/{app → support}/models/label.rb +0 -0
  378. /data/spec/{app → support}/models/language.rb +0 -0
  379. /data/spec/{app → support}/models/lat_lng.rb +0 -0
  380. /data/spec/{app → support}/models/league.rb +0 -0
  381. /data/spec/{app → support}/models/learner.rb +0 -0
  382. /data/spec/{app → support}/models/line_item.rb +0 -0
  383. /data/spec/{app → support}/models/location.rb +0 -0
  384. /data/spec/{app → support}/models/login.rb +0 -0
  385. /data/spec/{app → support}/models/manufacturer.rb +0 -0
  386. /data/spec/{app → support}/models/meat.rb +0 -0
  387. /data/spec/{app → support}/models/membership.rb +0 -0
  388. /data/spec/{app → support}/models/message.rb +0 -0
  389. /data/spec/{app → support}/models/minim.rb +0 -0
  390. /data/spec/{app → support}/models/mixed_drink.rb +0 -0
  391. /data/spec/{app → support}/models/movie.rb +0 -0
  392. /data/spec/{app → support}/models/my_hash.rb +0 -0
  393. /data/spec/{app → support}/models/name.rb +0 -0
  394. /data/spec/{app → support}/models/name_only.rb +0 -0
  395. /data/spec/{app → support}/models/node.rb +0 -0
  396. /data/spec/{app → support}/models/note.rb +0 -0
  397. /data/spec/{app → support}/models/odd.rb +0 -0
  398. /data/spec/{app → support}/models/ordered_post.rb +0 -0
  399. /data/spec/{app → support}/models/ordered_preference.rb +0 -0
  400. /data/spec/{app → support}/models/oscar.rb +0 -0
  401. /data/spec/{app → support}/models/other_owner_object.rb +0 -0
  402. /data/spec/{app → support}/models/override.rb +0 -0
  403. /data/spec/{app → support}/models/ownable.rb +0 -0
  404. /data/spec/{app → support}/models/pack.rb +0 -0
  405. /data/spec/{app → support}/models/page.rb +0 -0
  406. /data/spec/{app → support}/models/page_question.rb +0 -0
  407. /data/spec/{app → support}/models/parent.rb +0 -0
  408. /data/spec/{app → support}/models/parent_doc.rb +0 -0
  409. /data/spec/{app → support}/models/passport.rb +0 -0
  410. /data/spec/{app → support}/models/patient.rb +0 -0
  411. /data/spec/{app → support}/models/pdf_writer.rb +0 -0
  412. /data/spec/{app → support}/models/pencil.rb +0 -0
  413. /data/spec/{app → support}/models/pet.rb +0 -0
  414. /data/spec/{app → support}/models/pet_owner.rb +0 -0
  415. /data/spec/{app → support}/models/phone.rb +0 -0
  416. /data/spec/{app → support}/models/pizza.rb +0 -0
  417. /data/spec/{app → support}/models/player.rb +0 -0
  418. /data/spec/{app → support}/models/post.rb +0 -0
  419. /data/spec/{app → support}/models/post_genre.rb +0 -0
  420. /data/spec/{app → support}/models/powerup.rb +0 -0
  421. /data/spec/{app → support}/models/preference.rb +0 -0
  422. /data/spec/{app → support}/models/princess.rb +0 -0
  423. /data/spec/{app → support}/models/product.rb +0 -0
  424. /data/spec/{app → support}/models/pronunciation.rb +0 -0
  425. /data/spec/{app → support}/models/pub.rb +0 -0
  426. /data/spec/{app → support}/models/publication/encyclopedia.rb +0 -0
  427. /data/spec/{app → support}/models/publication/review.rb +0 -0
  428. /data/spec/{app → support}/models/purchase.rb +0 -0
  429. /data/spec/{app → support}/models/question.rb +0 -0
  430. /data/spec/{app → support}/models/quiz.rb +0 -0
  431. /data/spec/{app → support}/models/rating.rb +0 -0
  432. /data/spec/{app → support}/models/record.rb +0 -0
  433. /data/spec/{app → support}/models/registry.rb +0 -0
  434. /data/spec/{app → support}/models/role.rb +0 -0
  435. /data/spec/{app → support}/models/root_category.rb +0 -0
  436. /data/spec/{app → support}/models/sandwich.rb +0 -0
  437. /data/spec/{app → support}/models/scheduler.rb +0 -0
  438. /data/spec/{app → support}/models/seo.rb +0 -0
  439. /data/spec/{app → support}/models/series.rb +0 -0
  440. /data/spec/{app → support}/models/server.rb +0 -0
  441. /data/spec/{app → support}/models/service.rb +0 -0
  442. /data/spec/{app → support}/models/shelf.rb +0 -0
  443. /data/spec/{app → support}/models/shipment_address.rb +0 -0
  444. /data/spec/{app → support}/models/shipping_container.rb +0 -0
  445. /data/spec/{app → support}/models/shipping_pack.rb +0 -0
  446. /data/spec/{app → support}/models/shop.rb +0 -0
  447. /data/spec/{app → support}/models/short_agent.rb +0 -0
  448. /data/spec/{app → support}/models/short_quiz.rb +0 -0
  449. /data/spec/{app → support}/models/simple.rb +0 -0
  450. /data/spec/{app → support}/models/slave.rb +0 -0
  451. /data/spec/{app → support}/models/song.rb +0 -0
  452. /data/spec/{app → support}/models/sound.rb +0 -0
  453. /data/spec/{app → support}/models/square.rb +0 -0
  454. /data/spec/{app → support}/models/staff.rb +0 -0
  455. /data/spec/{app → support}/models/store_as_dup_test1.rb +0 -0
  456. /data/spec/{app → support}/models/store_as_dup_test2.rb +0 -0
  457. /data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  458. /data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  459. /data/spec/{app → support}/models/strategy.rb +0 -0
  460. /data/spec/{app → support}/models/sub_item.rb +0 -0
  461. /data/spec/{app → support}/models/subscription.rb +0 -0
  462. /data/spec/{app → support}/models/survey.rb +0 -0
  463. /data/spec/{app → support}/models/symptom.rb +0 -0
  464. /data/spec/{app → support}/models/tag.rb +0 -0
  465. /data/spec/{app → support}/models/target.rb +0 -0
  466. /data/spec/{app → support}/models/template.rb +0 -0
  467. /data/spec/{app → support}/models/thing.rb +0 -0
  468. /data/spec/{app → support}/models/title.rb +0 -0
  469. /data/spec/{app → support}/models/topping.rb +0 -0
  470. /data/spec/{app → support}/models/track.rb +0 -0
  471. /data/spec/{app → support}/models/translation.rb +0 -0
  472. /data/spec/{app → support}/models/tree.rb +0 -0
  473. /data/spec/{app → support}/models/updatable.rb +0 -0
  474. /data/spec/{app → support}/models/user.rb +0 -0
  475. /data/spec/{app → support}/models/user_account.rb +0 -0
  476. /data/spec/{app → support}/models/validation_callback.rb +0 -0
  477. /data/spec/{app → support}/models/version.rb +0 -0
  478. /data/spec/{app → support}/models/vertex.rb +0 -0
  479. /data/spec/{app → support}/models/vet_visit.rb +0 -0
  480. /data/spec/{app → support}/models/video.rb +0 -0
  481. /data/spec/{app → support}/models/video_game.rb +0 -0
  482. /data/spec/{app → support}/models/weapon.rb +0 -0
  483. /data/spec/{app → support}/models/wiki_page.rb +0 -0
  484. /data/spec/{app → support}/models/word.rb +0 -0
  485. /data/spec/{app → support}/models/word_origin.rb +0 -0
@@ -39,7 +39,8 @@ module Mongoid
39
39
  #
40
40
  # @since 3.0.0
41
41
  def validate(klass, name, options)
42
- validate_name(klass, name, options)
42
+ validate_field_name(klass, name)
43
+ validate_name_uniqueness(klass, name, options)
43
44
  validate_options(klass, name, options)
44
45
  end
45
46
 
@@ -61,28 +62,40 @@ module Mongoid
61
62
  end
62
63
  end
63
64
 
64
- private
65
-
66
- # Determine if the field name is allowed, if not raise an error.
67
- #
68
- # @api private
65
+ # Determine if the field name is valid, if not raise an error.
69
66
  #
70
67
  # @example Check the field name.
71
- # Macro.validate_name(Model, :name)
68
+ # Macro.validate_field_name(Model, :name)
72
69
  #
73
70
  # @param [ Class ] klass The model class.
74
71
  # @param [ Symbol ] name The field name.
75
72
  #
76
73
  # @raise [ Errors::InvalidField ] If the name is not allowed.
77
74
  #
78
- # @since 3.0.0
79
- def validate_name(klass, name, options)
75
+ # @api private
76
+ def validate_field_name(klass, name)
80
77
  [name, "#{name}?".to_sym, "#{name}=".to_sym].each do |n|
81
78
  if Mongoid.destructive_fields.include?(n)
82
79
  raise Errors::InvalidField.new(klass, n)
83
80
  end
84
81
  end
82
+ end
85
83
 
84
+ private
85
+
86
+ # Determine if the field name is unique, if not raise an error.
87
+ #
88
+ # @example Check the field name.
89
+ # Macro.validate_name_uniqueness(Model, :name, {})
90
+ #
91
+ # @param [ Class ] klass The model class.
92
+ # @param [ Symbol ] name The field name.
93
+ # @param [ Hash ] options The provided options.
94
+ #
95
+ # @raise [ Errors::InvalidField ] If the name is not allowed.
96
+ #
97
+ # @api private
98
+ def validate_name_uniqueness(klass, name, options)
86
99
  if !options[:overwrite] && klass.fields.keys.include?(name.to_s)
87
100
  if Mongoid.duplicate_fields_exception
88
101
  raise Errors::InvalidField.new(klass, name)
@@ -12,6 +12,8 @@ module Mongoid
12
12
  module Fields
13
13
  extend ActiveSupport::Concern
14
14
 
15
+ StringifiedSymbol = Mongoid::StringifiedSymbol
16
+
15
17
  # For fields defined with symbols use the correct class.
16
18
  #
17
19
  # @since 4.0.0
@@ -30,6 +32,7 @@ module Mongoid
30
32
  regexp: Regexp,
31
33
  set: Set,
32
34
  string: String,
35
+ stringified_symbol: StringifiedSymbol,
33
36
  symbol: Symbol,
34
37
  time: Time
35
38
  }.with_indifferent_access
@@ -60,6 +60,16 @@ module Mongoid
60
60
  with_default_scope.count
61
61
  end
62
62
 
63
+ # Returns an estimated count of records in the database.
64
+ #
65
+ # @example Get the count of matching documents.
66
+ # Person.estimated_count
67
+ #
68
+ # @return [ Integer ] The number of matching documents.
69
+ def estimated_count
70
+ with_default_scope.estimated_count
71
+ end
72
+
63
73
  # Returns true if count is zero
64
74
  #
65
75
  # @example Are there no saved documents for this model?
@@ -81,20 +91,46 @@ module Mongoid
81
91
  with_default_scope.exists?
82
92
  end
83
93
 
84
- # Find a +Document+ in several different ways.
85
- #
86
- # If a +String+ is provided, it will be assumed that it is a
87
- # representation of a Mongo::ObjectID and will attempt to find a single
88
- # +Document+ based on that id. If a +Symbol+ and +Hash+ is provided then
89
- # it will attempt to find either a single +Document+ or multiples based
90
- # on the conditions provided and the first parameter.
91
- #
92
- # @example Find a single document by an id.
93
- # Person.find(BSON::ObjectId)
94
- #
95
- # @param [ Array ] args An assortment of finder options.
96
- #
97
- # @return [ Document, nil, Criteria ] A document or matching documents.
94
+ # Finds a +Document+ or multiple documents by their _id values.
95
+ #
96
+ # If a single non-Array argument is given, this argument is interpreted
97
+ # as the _id value of a document to find. If there is a matching document
98
+ # in the database, this document is returned; otherwise, if the
99
+ # +raise_not_found_error+ Mongoid configuration option is truthy
100
+ # (which is the default), +Errors::DocumentNotFound+ is raised, and if
101
+ # +raise_not_found_error+ is falsy, +find+ returns +nil+.
102
+ #
103
+ # If multiple arguments are given, or an Array argument is given, the
104
+ # array is flattened and each array element is interpreted as the _id
105
+ # value of the document to find. Mongoid then attempts to retrieve all
106
+ # documents with the provided _id values. The return value is an array
107
+ # of found documents. Each document appears one time in the returned array,
108
+ # even if its _id is given multiple times in the argument to +find+.
109
+ # If the +raise_not_found_error+ Mongoid configuration option is truthy,
110
+ # +Errors::DocumentNotFound+ exception is raised if any of the specified
111
+ # _ids were not found in the database. If the ++raise_not_found_error+
112
+ # Mongoid configuration option is falsy, only those documents which are
113
+ # found are returned; if no documents are found, the return value is an
114
+ # empty array.
115
+ #
116
+ # Note that MongoDB does not allow the _id field to be an array.
117
+ #
118
+ # The argument undergoes customary Mongoid type conversions based on
119
+ # the type declared for the _id field. By default the _id field is a
120
+ # +BSON::ObjectId+; this allows strings to be passed to +find+ and the
121
+ # strings will be transparently converted to +BSON::ObjectId+ instances
122
+ # during query construction.
123
+ #
124
+ # The +find+ method takes into account the default scope defined on the
125
+ # model class, if any.
126
+ #
127
+ # @param [ Object | Array<Object> ] args The _id values to find or an
128
+ # array thereof.
129
+ #
130
+ # @return [ Document | Array<Document> | nil ] A document or matching documents.
131
+ #
132
+ # @raise Errors::DocumentNotFound If not all documents are found and
133
+ # the +raise_not_found_error+ Mongoid configuration option is truthy.
98
134
  def find(*args)
99
135
  with_default_scope.find(*args)
100
136
  end
@@ -82,8 +82,8 @@ module Mongoid
82
82
  #
83
83
  # @since 1.0.0
84
84
  def add_indexes
85
- if hereditary? && !index_keys.include?(_type: 1)
86
- index({ _type: 1 }, unique: false, background: true)
85
+ if hereditary? && !index_keys.include?(self.discriminator_key.to_sym => 1)
86
+ index({ self.discriminator_key.to_sym => 1 }, unique: false, background: true)
87
87
  end
88
88
  true
89
89
  end
@@ -125,7 +125,7 @@ module Mongoid
125
125
  # @return [ Document ] The document
126
126
  #
127
127
  # @since 2.3.0
128
- ruby2_keywords def run_callbacks(kind, *args, &block)
128
+ def run_callbacks(kind, *args, &block)
129
129
  cascadable_children(kind).each do |child|
130
130
  if child.run_callbacks(child_callback_type(kind, child), *args) == false
131
131
  return false
@@ -234,11 +234,9 @@ module Mongoid
234
234
  # document.halted_callback_hook(filter)
235
235
  #
236
236
  # @param [ Symbol ] filter The callback that halted.
237
- # @param [ Symbol ] name The name of the callback that was halted
238
- # (requires Rails 6.1+)
239
237
  #
240
238
  # @since 3.0.3
241
- def halted_callback_hook(filter, name = nil)
239
+ def halted_callback_hook(filter)
242
240
  @before_callback_halted = true
243
241
  end
244
242
 
@@ -1,24 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # encoding: utf-8
3
3
 
4
- require "mongoid/matchable/default"
5
- require "mongoid/matchable/all"
6
- require "mongoid/matchable/and"
7
- require "mongoid/matchable/elem_match"
8
- require "mongoid/matchable/eq"
9
- require "mongoid/matchable/exists"
10
- require "mongoid/matchable/gt"
11
- require "mongoid/matchable/gte"
12
- require "mongoid/matchable/in"
13
- require "mongoid/matchable/lt"
14
- require "mongoid/matchable/lte"
15
- require "mongoid/matchable/ne"
16
- require "mongoid/matchable/nin"
17
- require "mongoid/matchable/nor"
18
- require "mongoid/matchable/or"
19
- require "mongoid/matchable/regexp"
20
- require "mongoid/matchable/size"
21
-
22
4
  module Mongoid
23
5
 
24
6
  # This module contains all the behavior for Ruby implementations of MongoDB
@@ -28,27 +10,6 @@ module Mongoid
28
10
  module Matchable
29
11
  extend ActiveSupport::Concern
30
12
 
31
- # Hash lookup for the matcher for a specific operation.
32
- #
33
- # @since 1.0.0
34
- MATCHERS = {
35
- "$all" => All,
36
- "$and" => And,
37
- "$elemMatch" => ElemMatch,
38
- "$eq" => Eq,
39
- "$exists" => Exists,
40
- "$gt" => Gt,
41
- "$gte" => Gte,
42
- "$in" => In,
43
- "$lt" => Lt,
44
- "$lte" => Lte,
45
- "$ne" => Ne,
46
- "$nin" => Nin,
47
- "$nor" => Nor,
48
- "$or" => Or,
49
- "$size" => Size,
50
- }.with_indifferent_access.freeze
51
-
52
13
  # Determines if this document has the attributes to match the supplied
53
14
  # MongoDB selector. Used for matching on embedded associations.
54
15
  #
@@ -61,116 +22,7 @@ module Mongoid
61
22
  #
62
23
  # @since 1.0.0
63
24
  def _matches?(selector)
64
- selector.each_pair do |key, value|
65
- if value.is_a?(Hash)
66
- value.each do |item|
67
- if item[0].to_s == "$not".freeze
68
- item = item[1]
69
- return false if matcher(key, item)._matches?(item)
70
- else
71
- return false unless matcher(key, Hash[*item])._matches?(Hash[*item])
72
- end
73
- end
74
- else
75
- return false unless matcher(key, value)._matches?(value)
76
- end
77
- end
78
- true
79
- end
80
-
81
- private
82
-
83
- # Get the matcher for the supplied key and value. Will determine the class
84
- # name from the key.
85
- #
86
- # @example Get the matcher.
87
- # document.matcher(:title, { "$in" => [ "test" ] })
88
- #
89
- # @param [ Symbol, String ] key The field name.
90
- # @param [ Object, Hash ] value The value or selector.
91
- #
92
- # @return [ Matcher ] The matcher.
93
- #
94
- # @since 2.0.0.rc.7
95
- # @api private
96
- def matcher(key, value)
97
- Matchable.matcher(self, key, value)
98
- end
99
-
100
- class << self
101
-
102
- # Get the matcher for the supplied key and value. Will determine the class
103
- # name from the key.
104
- #
105
- # @api private
106
- #
107
- # @example Get the matcher.
108
- # Matchable.matcher(document, :title, { "$in" => [ "test" ] })
109
- #
110
- # @param [ Document ] document The document to check.
111
- # @param [ Symbol, String ] key The field name.
112
- # @param [ Object, Hash ] value The value or selector.
113
- #
114
- # @return [ Matcher ] The matcher.
115
- #
116
- # @since 2.0.0.rc.7
117
- def matcher(document, key, value)
118
- if value.is_a?(Hash)
119
- matcher = MATCHERS[value.keys.first]
120
- if matcher
121
- matcher.new(extract_attribute(document, key))
122
- else
123
- Default.new(extract_attribute(document, key))
124
- end
125
- elsif value.regexp?
126
- Regexp.new(extract_attribute(document, key))
127
- else
128
- case key.to_s
129
- when "$or" then Or.new(value, document)
130
- when "$and" then And.new(value, document)
131
- when "$nor" then Nor.new(value, document)
132
- else Default.new(extract_attribute(document, key))
133
- end
134
- end
135
- end
136
-
137
- private
138
-
139
- # Extract the attribute from the key, being smarter about dot notation.
140
- #
141
- # @api private
142
- #
143
- # @example Extract the attribute.
144
- # strategy.extract_attribute(doc, "info.field")
145
- #
146
- # @param [ Document ] document The document.
147
- # @param [ String ] key The key.
148
- #
149
- # @return [ Object ] The value of the attribute.
150
- #
151
- # @since 2.2.1
152
- # @api private
153
- def extract_attribute(document, key)
154
- if (key_string = key.to_s) =~ /.+\..+/
155
- key_string.split('.').inject(document.send(:as_attributes)) do |_attribs, _key|
156
- if _attribs.is_a?(::Array)
157
- if _key =~ /\A\d+\z/ && _attribs.none? {|doc| doc.is_a?(Hash)}
158
- _attribs.try(:[], _key.to_i)
159
- else
160
- _attribs.map { |doc| doc.try(:[], _key) }
161
- end
162
- else
163
- _attribs.try(:[], _key)
164
- end
165
- end
166
- else
167
- if document.is_a?(Hash)
168
- document[key_string]
169
- else
170
- document.attributes[key_string]
171
- end
172
- end
173
- end
25
+ Matcher::Expression.matches?(self, selector)
174
26
  end
175
27
  end
176
28
  end
@@ -0,0 +1,22 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module All
6
+ module_function def matches?(exists, value, condition)
7
+ unless Array === condition
8
+ raise Errors::InvalidQuery, "$all argument must be an array: #{Errors::InvalidQuery.truncate_expr(condition)}"
9
+ end
10
+
11
+ !condition.empty? && condition.all? do |c|
12
+ case c
13
+ when ::Regexp, BSON::Regexp::Raw
14
+ Regex.matches_array_or_scalar?(value, c)
15
+ else
16
+ EqImpl.matches?(true, value, c, '$all')
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module And
6
+ module_function def matches?(document, expr)
7
+ unless expr.is_a?(Array)
8
+ raise Errors::InvalidQuery, "$and argument must be an array: #{Errors::InvalidQuery.truncate_expr(expr)}"
9
+ end
10
+
11
+ if expr.empty?
12
+ raise Errors::InvalidQuery, "$and argument must be a non-empty array: #{Errors::InvalidQuery.truncate_expr(expr)}"
13
+ end
14
+
15
+ expr.all? do |sub_expr|
16
+ Expression.matches?(document, sub_expr)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module ElemMatch
6
+ module_function def matches?(exists, value, condition)
7
+ unless Hash === condition
8
+ raise Errors::InvalidQuery, "$elemMatch requires a Hash operand: #{Errors::InvalidQuery.truncate_expr(condition)}"
9
+ end
10
+ if Array === value && !value.empty?
11
+ value.any? do |v|
12
+ ElemMatchExpression.matches?(v, condition)
13
+ end
14
+ else
15
+ # Validate the condition is valid, even though we will never attempt
16
+ # matching it.
17
+ condition.each do |k, v|
18
+ if k.to_s.start_with?('$')
19
+ begin
20
+ ExpressionOperator.get(k)
21
+ rescue Mongoid::Errors::InvalidExpressionOperator
22
+ begin
23
+ FieldOperator.get(k)
24
+ rescue Mongoid::Errors::InvalidFieldOperator => exc
25
+ raise Mongoid::Errors::InvalidElemMatchOperator.new(exc.operator)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # $elemMatch argument can be a top-level expression and some specific
5
+ # operator combinations like $not with a regular expression.
6
+ #
7
+ # @api private
8
+ module ElemMatchExpression
9
+ module_function def matches?(document, expr)
10
+ Expression.matches?(document, expr)
11
+ rescue Mongoid::Errors::InvalidExpressionOperator
12
+ begin
13
+ FieldExpression.matches?(true, document, expr)
14
+ rescue Mongoid::Errors::InvalidFieldOperator => exc
15
+ raise Mongoid::Errors::InvalidElemMatchOperator.new(exc.operator)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module Eq
6
+ module_function def matches?(exists, value, condition)
7
+ EqImpl.matches?(exists, value, condition, '$eq')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # This module is used by $eq and other operators that need to perform
5
+ # the matching that $eq performs (for example, $ne which negates the result
6
+ # of $eq). Unlike $eq this module takes an original operator as an
7
+ # additional argument to +matches?+ to provide the correct exception
8
+ # messages reflecting the operator that was first invoked.
9
+ #
10
+ # @api private
11
+ module EqImpl
12
+ module_function def matches?(exists, value, condition, original_operator)
13
+ case condition
14
+ when Range
15
+ # Since $ne invokes $eq, the exception message needs to handle
16
+ # both operators.
17
+ raise Errors::InvalidQuery, "Range is not supported as an argument to '#{original_operator}'"
18
+ =begin
19
+ if value.is_a?(Array)
20
+ value.any? { |elt| condition.include?(elt) }
21
+ else
22
+ condition.include?(value)
23
+ end
24
+ =end
25
+ else
26
+ value == condition ||
27
+ value.is_a?(Array) && value.include?(condition)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # This is an internal equality implementation that performs exact
5
+ # comparisons and regular expression matches.
6
+ #
7
+ # @api private
8
+ module EqImplWithRegexp
9
+ module_function def matches?(original_operator, value, condition)
10
+ case condition
11
+ when Regexp
12
+ value =~ condition
13
+ when ::BSON::Regexp::Raw
14
+ value =~ condition.compile
15
+ else
16
+ value == condition
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module Exists
6
+ module_function def matches?(exists, value, condition)
7
+ case condition
8
+ when Range
9
+ raise Errors::InvalidQuery, "$exists argument cannot be a Range: #{Errors::InvalidQuery.truncate_expr(condition)}"
10
+ end
11
+ exists == (condition || false)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,40 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module Expression
6
+ module_function def matches?(document, expr)
7
+ if expr.nil?
8
+ raise Errors::InvalidQuery, "Nil condition in expression context"
9
+ end
10
+ unless Hash === expr
11
+ raise Errors::InvalidQuery, "MQL query must be provided as a Hash"
12
+ end
13
+ expr.all? do |k, expr_v|
14
+ k = k.to_s
15
+ if k.start_with?('$')
16
+ ExpressionOperator.get(k).matches?(document, expr_v)
17
+ else
18
+ exists, value, expanded = Matcher.extract_attribute(document, k)
19
+ # The value may have been expanded into an array, but then
20
+ # array may have been shrunk back to a scalar (or hash) when
21
+ # path contained a numeric position.
22
+ # Do not treat a hash as an array here (both are iterable).
23
+ if expanded && Array === value
24
+ if value == []
25
+ # Empty array is technically equivalent to exists: false.
26
+ FieldExpression.matches?(false, nil, expr_v)
27
+ else
28
+ value.any? do |v|
29
+ FieldExpression.matches?(true, v, expr_v)
30
+ end
31
+ end
32
+ else
33
+ FieldExpression.matches?(exists, value, expr_v)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module ExpressionOperator
6
+ MAP = {
7
+ '$and' => And,
8
+ '$nor' => Nor,
9
+ '$or' => Or,
10
+ }.freeze
11
+
12
+ module_function def get(op)
13
+ MAP.fetch(op)
14
+ rescue KeyError
15
+ raise Errors::InvalidExpressionOperator.new(op)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,63 @@
1
+ module Mongoid
2
+ module Matcher
3
+
4
+ # @api private
5
+ module FieldExpression
6
+ module_function def matches?(exists, value, condition)
7
+ if condition.is_a?(Hash)
8
+ condition.all? do |k, cond_v|
9
+ k = k.to_s
10
+ if k.start_with?('$')
11
+ if %w($regex $options).include?(k)
12
+ unless condition.key?('$regex')
13
+ raise Errors::InvalidQuery, "$regex is required if $options is given: #{Errors::InvalidQuery.truncate_expr(condition)}"
14
+ end
15
+
16
+ if k == '$regex'
17
+ if options = condition['$options']
18
+ cond_v = case cond_v
19
+ when Regexp
20
+ BSON::Regexp::Raw.new(cond_v.source, options)
21
+ when BSON::Regexp::Raw
22
+ BSON::Regexp::Raw.new(cond_v.pattern, options)
23
+ else
24
+ BSON::Regexp::Raw.new(cond_v, options)
25
+ end
26
+ elsif String === cond_v
27
+ cond_v = BSON::Regexp::Raw.new(cond_v)
28
+ end
29
+
30
+ FieldOperator.get(k).matches?(exists, value, cond_v)
31
+ else
32
+ # $options are matched as part of $regex
33
+ true
34
+ end
35
+ else
36
+ FieldOperator.get(k).matches?(exists, value, cond_v)
37
+ end
38
+ elsif Hash === value
39
+ sub_exists, sub_value, expanded =
40
+ Matcher.extract_attribute(value, k)
41
+ if expanded
42
+ sub_value.any? do |sub_v|
43
+ Eq.matches?(true, sub_v, cond_v)
44
+ end
45
+ else
46
+ Eq.matches?(sub_exists, sub_value, cond_v)
47
+ end
48
+ else
49
+ false
50
+ end
51
+ end
52
+ else
53
+ case condition
54
+ when ::Regexp, BSON::Regexp::Raw
55
+ Regex.matches_array_or_scalar?(value, condition)
56
+ else
57
+ Eq.matches?(exists, value, condition)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end