mongoid 7.1.0.rc0 → 7.2.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (508) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +6 -6
  5. data/LICENSE +1 -1
  6. data/README.md +14 -7
  7. data/Rakefile +21 -0
  8. data/lib/config/locales/en.yml +42 -6
  9. data/lib/mongoid.rb +26 -2
  10. data/lib/mongoid/association/accessors.rb +37 -2
  11. data/lib/mongoid/association/depending.rb +1 -6
  12. data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
  14. data/lib/mongoid/association/many.rb +5 -4
  15. data/lib/mongoid/association/proxy.rb +6 -4
  16. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -1
  17. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  18. data/lib/mongoid/association/referenced/belongs_to/eager.rb +38 -2
  19. data/lib/mongoid/association/referenced/eager.rb +29 -9
  20. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
  21. data/lib/mongoid/association/referenced/has_many/enumerable.rb +30 -15
  22. data/lib/mongoid/association/referenced/has_many/proxy.rb +11 -3
  23. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  24. data/lib/mongoid/atomic.rb +13 -3
  25. data/lib/mongoid/atomic/modifiers.rb +1 -1
  26. data/lib/mongoid/attributes.rb +28 -20
  27. data/lib/mongoid/attributes/dynamic.rb +1 -1
  28. data/lib/mongoid/clients/factory.rb +19 -2
  29. data/lib/mongoid/clients/options.rb +8 -8
  30. data/lib/mongoid/clients/sessions.rb +20 -4
  31. data/lib/mongoid/clients/storage_options.rb +5 -5
  32. data/lib/mongoid/composable.rb +1 -0
  33. data/lib/mongoid/config.rb +45 -12
  34. data/lib/mongoid/config/options.rb +5 -2
  35. data/lib/mongoid/contextual.rb +5 -4
  36. data/lib/mongoid/contextual/geo_near.rb +3 -2
  37. data/lib/mongoid/contextual/map_reduce.rb +3 -2
  38. data/lib/mongoid/contextual/mongo.rb +25 -5
  39. data/lib/mongoid/copyable.rb +2 -2
  40. data/lib/mongoid/criteria.rb +80 -11
  41. data/lib/mongoid/criteria/modifiable.rb +2 -1
  42. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  43. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +6 -6
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  45. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  46. data/lib/mongoid/criteria/queryable/mergeable.rb +75 -8
  47. data/lib/mongoid/criteria/queryable/pipeline.rb +3 -2
  48. data/lib/mongoid/criteria/queryable/selectable.rb +141 -19
  49. data/lib/mongoid/criteria/queryable/selector.rb +3 -3
  50. data/lib/mongoid/criteria/queryable/storable.rb +106 -101
  51. data/lib/mongoid/document.rb +15 -3
  52. data/lib/mongoid/errors.rb +7 -0
  53. data/lib/mongoid/errors/eager_load.rb +2 -0
  54. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +25 -0
  55. data/lib/mongoid/errors/invalid_elem_match_operator.rb +33 -0
  56. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +26 -0
  57. data/lib/mongoid/errors/invalid_expression_operator.rb +28 -0
  58. data/lib/mongoid/errors/invalid_field_operator.rb +33 -0
  59. data/lib/mongoid/errors/invalid_query.rb +41 -0
  60. data/lib/mongoid/errors/no_client_config.rb +2 -2
  61. data/lib/mongoid/errors/no_default_client.rb +1 -1
  62. data/lib/mongoid/extensions/hash.rb +4 -2
  63. data/lib/mongoid/extensions/regexp.rb +1 -1
  64. data/lib/mongoid/factory.rb +27 -10
  65. data/lib/mongoid/fields.rb +2 -1
  66. data/lib/mongoid/fields/standard.rb +2 -1
  67. data/lib/mongoid/fields/validators/macro.rb +26 -10
  68. data/lib/mongoid/findable.rb +55 -18
  69. data/lib/mongoid/indexable.rb +2 -2
  70. data/lib/mongoid/interceptable.rb +5 -1
  71. data/lib/mongoid/matchable.rb +1 -149
  72. data/lib/mongoid/matcher.rb +127 -0
  73. data/lib/mongoid/matcher/all.rb +22 -0
  74. data/lib/mongoid/matcher/and.rb +21 -0
  75. data/lib/mongoid/matcher/elem_match.rb +35 -0
  76. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  77. data/lib/mongoid/matcher/eq.rb +11 -0
  78. data/lib/mongoid/matcher/eq_impl.rb +32 -0
  79. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +21 -0
  80. data/lib/mongoid/matcher/exists.rb +15 -0
  81. data/lib/mongoid/matcher/expression.rb +40 -0
  82. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  83. data/lib/mongoid/matcher/field_expression.rb +63 -0
  84. data/lib/mongoid/matcher/field_operator.rb +52 -0
  85. data/lib/mongoid/matcher/gt.rb +17 -0
  86. data/lib/mongoid/matcher/gte.rb +17 -0
  87. data/lib/mongoid/matcher/in.rb +25 -0
  88. data/lib/mongoid/matcher/lt.rb +17 -0
  89. data/lib/mongoid/matcher/lte.rb +17 -0
  90. data/lib/mongoid/matcher/ne.rb +16 -0
  91. data/lib/mongoid/matcher/nin.rb +11 -0
  92. data/lib/mongoid/matcher/nor.rb +25 -0
  93. data/lib/mongoid/matcher/not.rb +29 -0
  94. data/lib/mongoid/matcher/or.rb +21 -0
  95. data/lib/mongoid/matcher/regex.rb +41 -0
  96. data/lib/mongoid/matcher/size.rb +26 -0
  97. data/lib/mongoid/persistable/deletable.rb +1 -1
  98. data/lib/mongoid/persistable/pushable.rb +11 -2
  99. data/lib/mongoid/persistence_context.rb +6 -6
  100. data/lib/mongoid/query_cache.rb +83 -38
  101. data/lib/mongoid/railties/database.rake +7 -0
  102. data/lib/mongoid/reloadable.rb +2 -2
  103. data/lib/mongoid/serializable.rb +11 -3
  104. data/lib/mongoid/shardable.rb +56 -4
  105. data/lib/mongoid/tasks/database.rake +10 -5
  106. data/lib/mongoid/tasks/database.rb +83 -0
  107. data/lib/mongoid/timestamps/timeless.rb +3 -1
  108. data/lib/mongoid/traversable.rb +111 -4
  109. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  110. data/lib/mongoid/version.rb +1 -1
  111. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -23
  112. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  113. data/spec/integration/app_spec.rb +254 -0
  114. data/spec/integration/associations/embedded_spec.rb +148 -0
  115. data/spec/integration/associations/has_many_spec.rb +69 -0
  116. data/spec/integration/associations/has_one_spec.rb +69 -0
  117. data/spec/integration/associations/nested_attributes_assignment_spec.rb +116 -0
  118. data/spec/integration/atomic/modifiers_spec.rb +117 -0
  119. data/spec/integration/bson_regexp_raw_spec.rb +20 -0
  120. data/spec/integration/criteria/date_field_spec.rb +41 -0
  121. data/spec/integration/criteria/logical_spec.rb +13 -0
  122. data/spec/integration/discriminator_key_spec.rb +354 -0
  123. data/spec/integration/discriminator_value_spec.rb +207 -0
  124. data/spec/integration/document_spec.rb +22 -0
  125. data/spec/integration/{matchable_spec.rb → matcher_examples_spec.rb} +120 -41
  126. data/spec/integration/matcher_operator_data/all.yml +140 -0
  127. data/spec/integration/matcher_operator_data/and.yml +93 -0
  128. data/spec/integration/matcher_operator_data/elem_match.yml +363 -0
  129. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  130. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  131. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  132. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  133. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  134. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  135. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  136. data/spec/integration/matcher_operator_data/implicit_traversal.yml +16 -0
  137. data/spec/integration/matcher_operator_data/in.yml +194 -0
  138. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  139. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  140. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  141. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  142. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  143. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  144. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  145. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  146. data/spec/integration/matcher_operator_data/not.yml +196 -0
  147. data/spec/integration/matcher_operator_data/or.yml +137 -0
  148. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  149. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  150. data/spec/integration/matcher_operator_data/size.yml +174 -0
  151. data/spec/integration/matcher_operator_spec.rb +100 -0
  152. data/spec/integration/matcher_spec.rb +189 -0
  153. data/spec/integration/server_query_spec.rb +142 -0
  154. data/spec/integration/shardable_spec.rb +149 -0
  155. data/spec/lite_spec_helper.rb +15 -4
  156. data/spec/mongoid/association/accessors_spec.rb +238 -63
  157. data/spec/mongoid/association/depending_spec.rb +78 -26
  158. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +33 -0
  159. data/spec/mongoid/association/embedded/embeds_many_models.rb +20 -0
  160. data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
  161. data/spec/mongoid/association/embedded/embeds_one_models.rb +1 -0
  162. data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
  163. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +193 -10
  164. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
  165. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +146 -68
  166. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +462 -187
  167. data/spec/mongoid/association/referenced/has_many_models.rb +9 -0
  168. data/spec/mongoid/association/referenced/has_one_models.rb +9 -0
  169. data/spec/mongoid/atomic/modifiers_spec.rb +47 -0
  170. data/spec/mongoid/atomic_spec.rb +23 -0
  171. data/spec/mongoid/attributes/nested_spec.rb +1 -1
  172. data/spec/mongoid/attributes_spec.rb +19 -7
  173. data/spec/mongoid/changeable_spec.rb +23 -0
  174. data/spec/mongoid/clients/factory_spec.rb +45 -8
  175. data/spec/mongoid/clients/options_spec.rb +11 -11
  176. data/spec/mongoid/clients/sessions_spec.rb +9 -10
  177. data/spec/mongoid/clients/transactions_spec.rb +20 -8
  178. data/spec/mongoid/clients_spec.rb +2 -2
  179. data/spec/mongoid/config_spec.rb +28 -0
  180. data/spec/mongoid/contextual/atomic_spec.rb +22 -11
  181. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  182. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  183. data/spec/mongoid/contextual/mongo_spec.rb +146 -69
  184. data/spec/mongoid/copyable_spec.rb +153 -1
  185. data/spec/mongoid/copyable_spec_models.rb +14 -0
  186. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +1 -1
  187. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  188. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
  189. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  190. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  191. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +45 -12
  192. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +1051 -392
  193. data/spec/mongoid/criteria/queryable/selectable_spec.rb +136 -82
  194. data/spec/mongoid/criteria/queryable/storable_spec.rb +80 -2
  195. data/spec/mongoid/criteria_spec.rb +240 -41
  196. data/spec/mongoid/document_fields_spec.rb +29 -0
  197. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  198. data/spec/mongoid/document_spec.rb +89 -15
  199. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  200. data/spec/mongoid/errors/no_client_config_spec.rb +2 -2
  201. data/spec/mongoid/errors/no_client_database_spec.rb +3 -3
  202. data/spec/mongoid/errors/no_client_hosts_spec.rb +3 -3
  203. data/spec/mongoid/factory_spec.rb +261 -28
  204. data/spec/mongoid/fields_spec.rb +72 -3
  205. data/spec/mongoid/findable_spec.rb +32 -0
  206. data/spec/mongoid/indexable_spec.rb +34 -6
  207. data/spec/mongoid/inspectable_spec.rb +29 -2
  208. data/spec/mongoid/interceptable_spec.rb +64 -2
  209. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  210. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +259 -0
  211. data/spec/mongoid/matcher/extract_attribute_spec.rb +47 -0
  212. data/spec/mongoid/persistable/creatable_spec.rb +108 -25
  213. data/spec/mongoid/persistable/deletable_spec.rb +86 -0
  214. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  215. data/spec/mongoid/persistable/savable_spec.rb +174 -16
  216. data/spec/mongoid/query_cache_middleware_spec.rb +16 -3
  217. data/spec/mongoid/query_cache_spec.rb +498 -29
  218. data/spec/mongoid/relations/proxy_spec.rb +1 -1
  219. data/spec/mongoid/reloadable_spec.rb +72 -0
  220. data/spec/mongoid/scopable_spec.rb +2 -1
  221. data/spec/mongoid/serializable_spec.rb +149 -20
  222. data/spec/mongoid/shardable_models.rb +61 -0
  223. data/spec/mongoid/shardable_spec.rb +69 -16
  224. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  225. data/spec/mongoid/tasks/database_spec.rb +1 -1
  226. data/spec/mongoid/traversable_spec.rb +1100 -0
  227. data/spec/spec_helper.rb +4 -33
  228. data/spec/support/child_process_helper.rb +79 -0
  229. data/spec/support/cluster_config.rb +3 -3
  230. data/spec/support/constraints.rb +50 -10
  231. data/spec/support/expectations.rb +3 -1
  232. data/spec/support/helpers.rb +11 -0
  233. data/spec/support/lite_constraints.rb +22 -0
  234. data/spec/{app → support}/models/account.rb +0 -0
  235. data/spec/{app → support}/models/acolyte.rb +0 -0
  236. data/spec/{app → support}/models/actor.rb +1 -1
  237. data/spec/{app → support}/models/actress.rb +0 -0
  238. data/spec/{app → support}/models/address.rb +0 -0
  239. data/spec/{app → support}/models/address_component.rb +0 -0
  240. data/spec/{app → support}/models/address_number.rb +0 -0
  241. data/spec/{app → support}/models/agency.rb +0 -0
  242. data/spec/{app → support}/models/agent.rb +0 -0
  243. data/spec/{app → support}/models/album.rb +0 -0
  244. data/spec/{app → support}/models/alert.rb +0 -0
  245. data/spec/{app → support}/models/animal.rb +0 -0
  246. data/spec/{app → support}/models/answer.rb +0 -0
  247. data/spec/{app → support}/models/appointment.rb +0 -0
  248. data/spec/support/models/armrest.rb +10 -0
  249. data/spec/{app → support}/models/array_field.rb +0 -0
  250. data/spec/{app → support}/models/article.rb +0 -0
  251. data/spec/{app → support}/models/artist.rb +0 -0
  252. data/spec/{app → support}/models/artwork.rb +0 -0
  253. data/spec/{app → support}/models/audio.rb +0 -0
  254. data/spec/{app → support}/models/augmentation.rb +0 -0
  255. data/spec/{app → support}/models/author.rb +0 -0
  256. data/spec/{app → support}/models/baby.rb +0 -0
  257. data/spec/{app → support}/models/band.rb +0 -0
  258. data/spec/{app → support}/models/bar.rb +0 -0
  259. data/spec/{app → support}/models/basic.rb +0 -0
  260. data/spec/{app → support}/models/bed.rb +0 -0
  261. data/spec/{app → support}/models/big_palette.rb +0 -0
  262. data/spec/{app → support}/models/birthday.rb +0 -0
  263. data/spec/{app → support}/models/bomb.rb +0 -0
  264. data/spec/{app → support}/models/book.rb +0 -0
  265. data/spec/{app → support}/models/breed.rb +0 -0
  266. data/spec/{app → support}/models/browser.rb +1 -1
  267. data/spec/{app → support}/models/building.rb +0 -0
  268. data/spec/{app → support}/models/building_address.rb +0 -0
  269. data/spec/{app → support}/models/bus.rb +0 -0
  270. data/spec/{app → support}/models/business.rb +0 -0
  271. data/spec/{app → support}/models/callback_test.rb +0 -0
  272. data/spec/{app → support}/models/canvas.rb +1 -1
  273. data/spec/{app → support}/models/car.rb +0 -0
  274. data/spec/{app → support}/models/cat.rb +0 -0
  275. data/spec/{app → support}/models/category.rb +0 -0
  276. data/spec/{app → support}/models/child.rb +0 -0
  277. data/spec/{app → support}/models/child_doc.rb +0 -0
  278. data/spec/{app → support}/models/church.rb +0 -0
  279. data/spec/{app → support}/models/circle.rb +0 -0
  280. data/spec/{app → support}/models/circuit.rb +0 -0
  281. data/spec/{app → support}/models/circus.rb +0 -0
  282. data/spec/{app → support}/models/code.rb +0 -0
  283. data/spec/support/models/coding.rb +4 -0
  284. data/spec/support/models/coding/pull_request.rb +12 -0
  285. data/spec/{app → support}/models/comment.rb +0 -0
  286. data/spec/{app → support}/models/company.rb +0 -0
  287. data/spec/{app → support}/models/consumption_period.rb +0 -0
  288. data/spec/{app → support}/models/contextable_item.rb +0 -0
  289. data/spec/{app → support}/models/contractor.rb +0 -0
  290. data/spec/{app → support}/models/cookie.rb +0 -0
  291. data/spec/{app → support}/models/country_code.rb +0 -0
  292. data/spec/{app → support}/models/courier_job.rb +0 -0
  293. data/spec/support/models/crate.rb +13 -0
  294. data/spec/support/models/deed.rb +8 -0
  295. data/spec/{app → support}/models/definition.rb +0 -0
  296. data/spec/support/models/delegating_patient.rb +16 -0
  297. data/spec/{app → support}/models/description.rb +0 -0
  298. data/spec/{app → support}/models/dictionary.rb +0 -0
  299. data/spec/{app → support}/models/division.rb +0 -0
  300. data/spec/{app → support}/models/doctor.rb +0 -0
  301. data/spec/{app → support}/models/dog.rb +0 -0
  302. data/spec/{app → support}/models/dokument.rb +0 -0
  303. data/spec/{app → support}/models/draft.rb +0 -0
  304. data/spec/{app → support}/models/dragon.rb +0 -0
  305. data/spec/{app → support}/models/driver.rb +1 -1
  306. data/spec/{app → support}/models/drug.rb +0 -0
  307. data/spec/{app → support}/models/dungeon.rb +0 -0
  308. data/spec/{app → support}/models/edit.rb +0 -0
  309. data/spec/{app → support}/models/email.rb +0 -0
  310. data/spec/{app → support}/models/employer.rb +0 -0
  311. data/spec/{app → support}/models/entry.rb +0 -0
  312. data/spec/{app → support}/models/eraser.rb +0 -0
  313. data/spec/{app → support}/models/even.rb +0 -0
  314. data/spec/{app → support}/models/event.rb +0 -0
  315. data/spec/{app → support}/models/exhibition.rb +0 -0
  316. data/spec/{app → support}/models/exhibitor.rb +0 -0
  317. data/spec/{app → support}/models/explosion.rb +0 -0
  318. data/spec/{app → support}/models/eye.rb +0 -0
  319. data/spec/{app → support}/models/eye_bowl.rb +0 -0
  320. data/spec/{app → support}/models/face.rb +0 -0
  321. data/spec/{app → support}/models/favorite.rb +0 -0
  322. data/spec/{app → support}/models/filesystem.rb +0 -0
  323. data/spec/{app → support}/models/fire_hydrant.rb +0 -0
  324. data/spec/{app → support}/models/firefox.rb +0 -0
  325. data/spec/{app → support}/models/fish.rb +0 -0
  326. data/spec/{app → support}/models/folder.rb +0 -0
  327. data/spec/{app → support}/models/folder_item.rb +0 -0
  328. data/spec/{app → support}/models/fruits.rb +0 -0
  329. data/spec/{app → support}/models/game.rb +0 -0
  330. data/spec/{app → support}/models/ghost.rb +0 -0
  331. data/spec/support/models/guitar.rb +5 -0
  332. data/spec/{app → support}/models/home.rb +0 -0
  333. data/spec/{app → support}/models/house.rb +0 -0
  334. data/spec/{app → support}/models/html_writer.rb +0 -0
  335. data/spec/{app → support}/models/id_key.rb +0 -0
  336. data/spec/support/models/idnodef.rb +8 -0
  337. data/spec/{app → support}/models/image.rb +0 -0
  338. data/spec/{app → support}/models/implant.rb +0 -0
  339. data/spec/support/models/instrument.rb +9 -0
  340. data/spec/{app → support}/models/item.rb +1 -1
  341. data/spec/{app → support}/models/jar.rb +0 -0
  342. data/spec/{app → support}/models/kaleidoscope.rb +0 -0
  343. data/spec/{app → support}/models/kangaroo.rb +0 -0
  344. data/spec/{app → support}/models/label.rb +0 -0
  345. data/spec/{app → support}/models/language.rb +0 -0
  346. data/spec/{app → support}/models/lat_lng.rb +0 -0
  347. data/spec/{app → support}/models/league.rb +0 -0
  348. data/spec/{app → support}/models/learner.rb +0 -0
  349. data/spec/{app → support}/models/line_item.rb +0 -0
  350. data/spec/{app → support}/models/location.rb +0 -0
  351. data/spec/{app → support}/models/login.rb +0 -0
  352. data/spec/{app → support}/models/manufacturer.rb +0 -0
  353. data/spec/{app → support}/models/meat.rb +0 -0
  354. data/spec/{app → support}/models/membership.rb +0 -0
  355. data/spec/{app → support}/models/message.rb +0 -0
  356. data/spec/{app → support}/models/minim.rb +0 -0
  357. data/spec/{app → support}/models/mixed_drink.rb +0 -0
  358. data/spec/support/models/mop.rb +16 -0
  359. data/spec/{app → support}/models/movie.rb +0 -0
  360. data/spec/{app → support}/models/my_hash.rb +0 -0
  361. data/spec/{app → support}/models/name.rb +0 -0
  362. data/spec/{app → support}/models/name_only.rb +0 -0
  363. data/spec/{app → support}/models/node.rb +0 -0
  364. data/spec/{app → support}/models/note.rb +0 -0
  365. data/spec/{app → support}/models/odd.rb +0 -0
  366. data/spec/{app → support}/models/ordered_post.rb +0 -0
  367. data/spec/{app → support}/models/ordered_preference.rb +0 -0
  368. data/spec/{app → support}/models/oscar.rb +0 -0
  369. data/spec/{app → support}/models/other_owner_object.rb +0 -0
  370. data/spec/{app → support}/models/override.rb +0 -0
  371. data/spec/{app → support}/models/ownable.rb +0 -0
  372. data/spec/{app → support}/models/owner.rb +2 -0
  373. data/spec/{app → support}/models/pack.rb +0 -0
  374. data/spec/{app → support}/models/page.rb +0 -0
  375. data/spec/{app → support}/models/page_question.rb +0 -0
  376. data/spec/{app → support}/models/palette.rb +1 -1
  377. data/spec/{app → support}/models/parent.rb +0 -0
  378. data/spec/{app → support}/models/parent_doc.rb +0 -0
  379. data/spec/{app → support}/models/passport.rb +1 -0
  380. data/spec/{app → support}/models/patient.rb +0 -0
  381. data/spec/{app → support}/models/pdf_writer.rb +0 -0
  382. data/spec/{app → support}/models/pencil.rb +0 -0
  383. data/spec/{app → support}/models/person.rb +1 -1
  384. data/spec/{app → support}/models/pet.rb +0 -0
  385. data/spec/{app → support}/models/pet_owner.rb +0 -0
  386. data/spec/{app → support}/models/phone.rb +1 -0
  387. data/spec/support/models/piano.rb +5 -0
  388. data/spec/{app → support}/models/pizza.rb +0 -0
  389. data/spec/{app → support}/models/player.rb +0 -0
  390. data/spec/{app → support}/models/post.rb +0 -0
  391. data/spec/{app → support}/models/post_genre.rb +0 -0
  392. data/spec/{app → support}/models/powerup.rb +0 -0
  393. data/spec/{app → support}/models/preference.rb +0 -0
  394. data/spec/{app → support}/models/princess.rb +0 -0
  395. data/spec/{app → support}/models/product.rb +0 -0
  396. data/spec/support/models/profile.rb +18 -0
  397. data/spec/{app → support}/models/pronunciation.rb +0 -0
  398. data/spec/{app → support}/models/pub.rb +0 -0
  399. data/spec/support/models/publication.rb +5 -0
  400. data/spec/support/models/publication/encyclopedia.rb +12 -0
  401. data/spec/support/models/publication/review.rb +14 -0
  402. data/spec/{app → support}/models/purchase.rb +0 -0
  403. data/spec/{app → support}/models/question.rb +0 -0
  404. data/spec/{app → support}/models/quiz.rb +0 -0
  405. data/spec/{app → support}/models/rating.rb +0 -0
  406. data/spec/{app → support}/models/record.rb +0 -0
  407. data/spec/{app → support}/models/registry.rb +0 -0
  408. data/spec/{app → support}/models/role.rb +0 -0
  409. data/spec/{app → support}/models/root_category.rb +0 -0
  410. data/spec/{app → support}/models/sandwich.rb +0 -0
  411. data/spec/{app → support}/models/scheduler.rb +0 -0
  412. data/spec/{app/models/profile.rb → support/models/scribe.rb} +2 -2
  413. data/spec/support/models/seat.rb +25 -0
  414. data/spec/{app → support}/models/seo.rb +0 -0
  415. data/spec/{app → support}/models/series.rb +0 -0
  416. data/spec/{app → support}/models/server.rb +0 -0
  417. data/spec/{app → support}/models/service.rb +0 -0
  418. data/spec/{app → support}/models/shape.rb +2 -2
  419. data/spec/{app → support}/models/shelf.rb +0 -0
  420. data/spec/{app → support}/models/shipment_address.rb +0 -0
  421. data/spec/{app → support}/models/shipping_container.rb +0 -0
  422. data/spec/{app → support}/models/shipping_pack.rb +0 -0
  423. data/spec/{app → support}/models/shop.rb +0 -0
  424. data/spec/{app → support}/models/short_agent.rb +0 -0
  425. data/spec/{app → support}/models/short_quiz.rb +0 -0
  426. data/spec/{app → support}/models/simple.rb +0 -0
  427. data/spec/{app → support}/models/slave.rb +0 -0
  428. data/spec/{app → support}/models/song.rb +0 -0
  429. data/spec/{app → support}/models/sound.rb +0 -0
  430. data/spec/{app → support}/models/square.rb +0 -0
  431. data/spec/{app → support}/models/staff.rb +0 -0
  432. data/spec/{app → support}/models/store_as_dup_test1.rb +0 -0
  433. data/spec/{app → support}/models/store_as_dup_test2.rb +0 -0
  434. data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  435. data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  436. data/spec/{app → support}/models/strategy.rb +0 -0
  437. data/spec/{app → support}/models/sub_item.rb +0 -0
  438. data/spec/{app → support}/models/subscription.rb +0 -0
  439. data/spec/{app → support}/models/survey.rb +0 -0
  440. data/spec/{app → support}/models/symptom.rb +0 -0
  441. data/spec/support/models/system_role.rb +7 -0
  442. data/spec/{app → support}/models/tag.rb +0 -0
  443. data/spec/{app → support}/models/target.rb +0 -0
  444. data/spec/{app → support}/models/template.rb +0 -0
  445. data/spec/{app → support}/models/thing.rb +0 -0
  446. data/spec/{app → support}/models/title.rb +0 -0
  447. data/spec/{app → support}/models/tool.rb +2 -2
  448. data/spec/{app → support}/models/topping.rb +0 -0
  449. data/spec/support/models/toy.rb +10 -0
  450. data/spec/{app → support}/models/track.rb +0 -0
  451. data/spec/{app → support}/models/translation.rb +0 -0
  452. data/spec/{app → support}/models/tree.rb +0 -0
  453. data/spec/{app → support}/models/truck.rb +2 -0
  454. data/spec/{app → support}/models/updatable.rb +0 -0
  455. data/spec/{app → support}/models/user.rb +0 -0
  456. data/spec/{app → support}/models/user_account.rb +0 -0
  457. data/spec/{app → support}/models/validation_callback.rb +0 -0
  458. data/spec/{app → support}/models/vehicle.rb +7 -2
  459. data/spec/{app → support}/models/version.rb +0 -0
  460. data/spec/{app → support}/models/vertex.rb +0 -0
  461. data/spec/{app → support}/models/vet_visit.rb +0 -0
  462. data/spec/{app → support}/models/video.rb +0 -0
  463. data/spec/{app → support}/models/video_game.rb +0 -0
  464. data/spec/{app → support}/models/weapon.rb +0 -0
  465. data/spec/{app → support}/models/wiki_page.rb +0 -0
  466. data/spec/{app → support}/models/word.rb +0 -0
  467. data/spec/{app → support}/models/word_origin.rb +0 -0
  468. data/spec/{app → support}/models/writer.rb +2 -2
  469. data/spec/support/session_registry.rb +50 -0
  470. data/spec/support/spec_config.rb +13 -5
  471. data/spec/support/spec_organizer.rb +130 -0
  472. metadata +882 -752
  473. metadata.gz.sig +0 -0
  474. data/lib/mongoid/matchable/all.rb +0 -30
  475. data/lib/mongoid/matchable/and.rb +0 -32
  476. data/lib/mongoid/matchable/default.rb +0 -121
  477. data/lib/mongoid/matchable/elem_match.rb +0 -36
  478. data/lib/mongoid/matchable/eq.rb +0 -23
  479. data/lib/mongoid/matchable/exists.rb +0 -25
  480. data/lib/mongoid/matchable/gt.rb +0 -25
  481. data/lib/mongoid/matchable/gte.rb +0 -25
  482. data/lib/mongoid/matchable/in.rb +0 -26
  483. data/lib/mongoid/matchable/lt.rb +0 -25
  484. data/lib/mongoid/matchable/lte.rb +0 -25
  485. data/lib/mongoid/matchable/ne.rb +0 -23
  486. data/lib/mongoid/matchable/nin.rb +0 -24
  487. data/lib/mongoid/matchable/nor.rb +0 -38
  488. data/lib/mongoid/matchable/or.rb +0 -35
  489. data/lib/mongoid/matchable/regexp.rb +0 -30
  490. data/lib/mongoid/matchable/size.rb +0 -23
  491. data/spec/mongoid/matchable/all_spec.rb +0 -34
  492. data/spec/mongoid/matchable/and_spec.rb +0 -190
  493. data/spec/mongoid/matchable/default_spec.rb +0 -140
  494. data/spec/mongoid/matchable/elem_match_spec.rb +0 -109
  495. data/spec/mongoid/matchable/eq_spec.rb +0 -49
  496. data/spec/mongoid/matchable/exists_spec.rb +0 -60
  497. data/spec/mongoid/matchable/gt_spec.rb +0 -89
  498. data/spec/mongoid/matchable/gte_spec.rb +0 -87
  499. data/spec/mongoid/matchable/in_spec.rb +0 -52
  500. data/spec/mongoid/matchable/lt_spec.rb +0 -88
  501. data/spec/mongoid/matchable/lte_spec.rb +0 -88
  502. data/spec/mongoid/matchable/ne_spec.rb +0 -49
  503. data/spec/mongoid/matchable/nin_spec.rb +0 -51
  504. data/spec/mongoid/matchable/nor_spec.rb +0 -210
  505. data/spec/mongoid/matchable/or_spec.rb +0 -134
  506. data/spec/mongoid/matchable/regexp_spec.rb +0 -62
  507. data/spec/mongoid/matchable/size_spec.rb +0 -28
  508. data/spec/mongoid/matchable_spec.rb +0 -856
@@ -173,6 +173,92 @@ describe Mongoid::Persistable::Deletable do
173
173
  end
174
174
  end
175
175
  end
176
+
177
+ context "when deleting all documents with a custom discriminator key" do
178
+ before do
179
+ Canvas.discriminator_key = "dkey"
180
+ end
181
+
182
+ after do
183
+ Canvas.discriminator_key = nil
184
+ end
185
+
186
+ let!(:firefox) do
187
+ Firefox.create(name: "firefox")
188
+ end
189
+
190
+ let!(:firefox2) do
191
+ Firefox.create(name: "firefox 2")
192
+ end
193
+
194
+ let!(:browser) do
195
+ Browser.create(name: "browser")
196
+ end
197
+
198
+ let!(:canvas) do
199
+ Canvas.create(name: "canvas")
200
+ end
201
+
202
+ before do
203
+ Firefox.delete_all
204
+ end
205
+
206
+ it "deletes from the parent class collection" do
207
+ expect(Canvas.count).to eq(2)
208
+ end
209
+
210
+ it "returns correct counts for child classes" do
211
+ expect(Firefox.count).to eq(0)
212
+ end
213
+
214
+ it "returns correct counts for root subclasses" do
215
+ expect(Browser.count).to eq(1)
216
+ end
217
+ end
218
+
219
+ context "when deleting all documents with a custom discriminator value" do
220
+ before do
221
+ Canvas.discriminator_key = "dkey"
222
+ Firefox.discriminator_value = "dvalue"
223
+ end
224
+
225
+ after do
226
+ Canvas.discriminator_key = nil
227
+ Firefox.discriminator_value = nil
228
+ end
229
+
230
+ let!(:firefox) do
231
+ Firefox.create(name: "firefox")
232
+ end
233
+
234
+ let!(:firefox2) do
235
+ Firefox.create(name: "firefox 2")
236
+ end
237
+
238
+ let!(:browser) do
239
+ Browser.create(name: "browser")
240
+ end
241
+
242
+ let!(:canvas) do
243
+ Canvas.create(name: "canvas")
244
+ end
245
+
246
+ before do
247
+ Firefox.delete_all
248
+ end
249
+
250
+ it "deletes from the parent class collection" do
251
+ expect(Canvas.count).to eq(2)
252
+ end
253
+
254
+ it "returns correct counts for child classes" do
255
+ expect(Firefox.count).to eq(0)
256
+ end
257
+
258
+ it "returns correct counts for root subclasses" do
259
+ expect(Browser.count).to eq(1)
260
+ end
261
+ end
176
262
  end
177
263
 
178
264
  describe "#delete_all" do
@@ -7,7 +7,7 @@ describe Mongoid::Persistable::Pushable do
7
7
 
8
8
  describe "#add_to_set" do
9
9
 
10
- context "when the document is a root document" do
10
+ context "when the document is a top level document" do
11
11
 
12
12
  shared_examples_for "a unique pushable root document" do
13
13
 
@@ -65,6 +65,60 @@ describe Mongoid::Persistable::Pushable do
65
65
 
66
66
  it_behaves_like "a unique pushable root document"
67
67
  end
68
+
69
+ context 'when the host model is not saved' do
70
+ context 'when attribute exists' do
71
+ let(:person) do
72
+ Person.new(aliases: [2])
73
+ end
74
+
75
+ it 'records the change' do
76
+ person.add_to_set({aliases: 1})
77
+
78
+ expect(person.aliases).to eq([2, 1])
79
+ end
80
+ end
81
+
82
+ context 'when attribute does not exist' do
83
+ let(:person) do
84
+ Person.new
85
+ end
86
+
87
+ it 'records the change' do
88
+ person.add_to_set({aliases: 1})
89
+
90
+ expect(person.aliases).to eq([1])
91
+ end
92
+ end
93
+ end
94
+
95
+ context 'when the host model is loaded from database' do
96
+ context 'when attribute exists' do
97
+ let(:person) do
98
+ Person.create!(aliases: [2])
99
+ person = Person.last
100
+ end
101
+
102
+ it 'records the change' do
103
+ person.add_to_set({aliases: 1})
104
+
105
+ expect(person.aliases).to eq([2, 1])
106
+ end
107
+ end
108
+
109
+ context 'when attribute does not exist' do
110
+ let(:person) do
111
+ Person.create!
112
+ person = Person.last
113
+ end
114
+
115
+ it 'records the change' do
116
+ person.add_to_set({aliases: 1})
117
+
118
+ expect(person.aliases).to eq([1])
119
+ end
120
+ end
121
+ end
68
122
  end
69
123
 
70
124
  context "when the document is embedded" do
@@ -165,35 +165,35 @@ describe Mongoid::Persistable::Savable do
165
165
 
166
166
  context "when performing modification and insert ops" do
167
167
 
168
- let(:person) do
169
- Person.create(title: "Blah")
168
+ let(:owner) do
169
+ Owner.create(name: "Blah")
170
170
  end
171
171
 
172
- let!(:address) do
173
- person.addresses.build(street: "Bond St")
172
+ let!(:birthday) do
173
+ owner.birthdays.build(title: "First")
174
174
  end
175
175
 
176
- let!(:name) do
177
- person.create_name(first_name: "Tony")
176
+ let!(:scribe) do
177
+ owner.create_scribe(name: "Josh")
178
178
  end
179
179
 
180
180
  let(:from_db) do
181
- Person.find(person.id)
181
+ Owner.find(owner.id)
182
182
  end
183
183
 
184
184
  before do
185
- person.title = "King"
186
- name.first_name = "Ryan"
185
+ owner.name = "King"
186
+ scribe.name = "Tosh"
187
187
  end
188
188
 
189
189
  it "persists with proper set and push modifiers" do
190
- expect(person.atomic_updates).to eq({
190
+ expect(owner.atomic_updates).to eq({
191
191
  "$set" => {
192
- "title" => "King",
193
- "name.first_name" => "Ryan"
192
+ "name" => "King",
193
+ "scribe.name" => "Tosh"
194
194
  },
195
195
  "$push"=> {
196
- "addresses" => { '$each' => [ { "_id" => address.id, "street" => "Bond St" } ] }
196
+ "birthdays" => { '$each' => [ { "_id" => birthday.id, "title" => "First" } ] }
197
197
  }
198
198
  })
199
199
  end
@@ -201,15 +201,15 @@ describe Mongoid::Persistable::Savable do
201
201
  context "when saving the document" do
202
202
 
203
203
  it "saves the root document" do
204
- expect(person.title).to eq("King")
204
+ expect(owner.name).to eq("King")
205
205
  end
206
206
 
207
207
  it "saves embedded many relations" do
208
- expect(person.addresses.first.street).to eq("Bond St")
208
+ expect(owner.birthdays.first.title).to eq("First")
209
209
  end
210
210
 
211
211
  it "saves embedded one relations" do
212
- expect(person.name.first_name).to eq("Ryan")
212
+ expect(owner.scribe.name).to eq("Tosh")
213
213
  end
214
214
  end
215
215
  end
@@ -258,6 +258,164 @@ describe Mongoid::Persistable::Savable do
258
258
  end
259
259
  end
260
260
 
261
+ context 'when adding documents to embedded associations on multiple levels' do
262
+ let!(:truck) { Truck.create! }
263
+ let!(:crate) { truck.crates.create!(volume: 0.4) }
264
+
265
+ it 'persists the new documents' do
266
+ expect(truck.crates.size).to eq 1
267
+ expect(truck.crates[0].volume).to eq 0.4
268
+ expect(truck.crates[0].toys.size).to eq 0
269
+
270
+ truck.crates.first.toys.build(name: "Teddy bear")
271
+ truck.crates.build(volume: 0.8)
272
+
273
+ # The following is equivalent to the two lines above:
274
+ #
275
+ # truck.crates_attributes = {
276
+ # '0' => {
277
+ # "toys_attributes" => {
278
+ # "0" => {
279
+ # "name" => "Teddy bear"
280
+ # }
281
+ # },
282
+ # "id" => crate.id.to_s
283
+ # },
284
+ # "1" => {
285
+ # "volume" => 0.8
286
+ # }
287
+ # }
288
+
289
+ expect(truck.crates.size).to eq 2
290
+ expect(truck.crates[0].volume).to eq 0.4
291
+ expect(truck.crates[0].toys.size).to eq 1
292
+ expect(truck.crates[0].toys[0].name).to eq "Teddy bear"
293
+ expect(truck.crates[1].volume).to eq 0.8
294
+ expect(truck.crates[1].toys.size).to eq 0
295
+
296
+ #expect(truck.atomic_updates[:conflicts]).to eq nil
297
+
298
+ expect { truck.save! }.not_to raise_error
299
+
300
+ _truck = Truck.find(truck.id)
301
+ expect(_truck.crates.size).to eq 2
302
+ expect(_truck.crates[0].volume).to eq 0.4
303
+ expect(_truck.crates[0].toys.size).to eq 1
304
+ expect(_truck.crates[0].toys[0].name).to eq "Teddy bear"
305
+ expect(_truck.crates[1].volume).to eq 0.8
306
+ expect(_truck.crates[1].toys.size).to eq 0
307
+ end
308
+ end
309
+
310
+ context 'when adding documents to embedded association and updating parent fields' do
311
+ let!(:truck) { Truck.create! }
312
+ let!(:crate) { truck.crates.create!(volume: 0.4) }
313
+
314
+ it 'performs all writes' do
315
+ truck.crates.build(volume: 1)
316
+ truck.crates.first.volume = 2
317
+
318
+ truck.save!
319
+
320
+ _truck = Truck.find(truck.id)
321
+ _truck.crates.length.should == 2
322
+ _truck.crates.first.volume.should == 2
323
+ _truck.crates.last.volume.should == 1
324
+ end
325
+ end
326
+
327
+ context 'when adding documents to nested embedded association and updating first association fields' do
328
+ let!(:truck) { Truck.create! }
329
+ let!(:seat) { truck.seats.create!(rating: 1) }
330
+
331
+ it 'performs all writes' do
332
+ truck.seats.first.armrests.build(side: 'left')
333
+ truck.seats.first.rating = 2
334
+
335
+ truck.save!
336
+
337
+ _truck = Truck.find(truck.id)
338
+ _truck.seats.length.should == 1
339
+ _truck.seats.first.armrests.length.should == 1
340
+ _truck.seats.first.armrests.first.side.should == 'left'
341
+ end
342
+ end
343
+
344
+ context 'when adding documents to nested embedded association and adding another top level association' do
345
+ let!(:truck) { Truck.create! }
346
+ let!(:crate) { truck.crates.create!(volume: 1) }
347
+
348
+ it 'performs all writes' do
349
+ truck.crates.first.toys.build(name: 'Bear')
350
+ truck.crates.build
351
+
352
+ truck.save!
353
+
354
+ _truck = Truck.find(truck.id)
355
+ _truck.crates.length.should == 2
356
+ _truck.crates.first.toys.length.should == 1
357
+ _truck.crates.first.toys.first.name.should == 'Bear'
358
+ _truck.crates.last.toys.length.should == 0
359
+ end
360
+
361
+ context 'when also updating first embedded top level association' do
362
+ it 'performs all writes' do
363
+ pending 'https://jira.mongodb.org/browse/MONGOID-4982'
364
+
365
+ truck.crates.first.volume = 2
366
+ truck.crates.first.toys.build(name: 'Bear')
367
+ truck.crates.build
368
+
369
+ truck.save!
370
+
371
+ _truck = Truck.find(truck.id)
372
+ _truck.crates.length.should == 2
373
+ _truck.crates.first.toys.length.should == 1
374
+ _truck.crates.first.toys.first.name.should == 'Bear'
375
+ _truck.crates.last.toys.length.should == 0
376
+ end
377
+ end
378
+ end
379
+
380
+ context 'when adding documents to embedded associations with cascaded callbacks on update' do
381
+ let!(:truck) { Truck.create! }
382
+ let!(:seat) { truck.seats.create!(rating: 1) }
383
+
384
+ it 'persists the new documents' do
385
+ expect(truck.seats.size).to eq 1
386
+ expect(truck.seats[0].rating).to eq 1
387
+
388
+ truck.seats.build
389
+
390
+ expect { truck.save! }.not_to raise_error
391
+
392
+ _truck = Truck.find(truck.id)
393
+ expect(_truck.seats.size).to eq 2
394
+ expect(_truck.seats[0].rating).to eq 1
395
+ expect(_truck.seats[1].rating).to eq 100
396
+ end
397
+
398
+ context 'when embedded association embeds another association' do
399
+ it 'persists the new documents' do
400
+ pending 'https://jira.mongodb.org/browse/MONGOID-4982'
401
+
402
+ expect(truck.seats.size).to eq 1
403
+ expect(truck.seats[0].rating).to eq 1
404
+
405
+ truck.seats.first.armrests.build
406
+ truck.seats.build
407
+
408
+ expect { truck.save! }.not_to raise_error
409
+
410
+ _truck = Truck.find(truck.id)
411
+ expect(_truck.seats.size).to eq 2
412
+ expect(_truck.seats[0].rating).to eq 1
413
+ expect(_truck.seats[0].armrests.length).to eq 1
414
+ expect(_truck.seats[1].rating).to eq 100
415
+ end
416
+ end
417
+ end
418
+
261
419
  context "when removing elements without using delete or destroy" do
262
420
 
263
421
  let!(:person) do
@@ -40,9 +40,22 @@ describe Mongoid::QueryCache::Middleware do
40
40
  expect(code).to eq(200)
41
41
  end
42
42
 
43
- it "cleans the query cache after reponds" do
44
- middleware.call({})
45
- expect(Mongoid::QueryCache.cache_table).to be_empty
43
+ context 'with driver query cache' do
44
+ min_driver_version '2.14'
45
+
46
+ it "cleans the query cache after it responds" do
47
+ middleware.call({})
48
+ expect(Mongo::QueryCache.send(:cache_table)).to be_empty
49
+ end
50
+ end
51
+
52
+ context 'with mongoid query cache' do
53
+ max_driver_version '2.13'
54
+
55
+ it "cleans the query cache after it responds" do
56
+ middleware.call({})
57
+ expect(Mongoid::QueryCache.cache_table).to be_empty
58
+ end
46
59
  end
47
60
  end
48
61
  end
@@ -10,6 +10,224 @@ describe Mongoid::QueryCache do
10
10
  Mongoid::QueryCache.cache { spec.run }
11
11
  end
12
12
 
13
+ before(:all) do
14
+ # It is likely that there are other session leaks in the driver
15
+ # and/or Mongoid that are unrelated to the query cache. Clear the
16
+ # SessionRegistry at the start of these tests in order to detect leaks that
17
+ # occur only within the scope of these tests.
18
+ #
19
+ # Other session leaks will be detected and addressed as part of RUBY-2391.
20
+ SessionRegistry.instance.clear_registry
21
+ end
22
+
23
+ after do
24
+ SessionRegistry.instance.verify_sessions_ended!
25
+ end
26
+
27
+ describe '#cache' do
28
+ context 'with driver query cache' do
29
+ min_driver_version '2.14'
30
+
31
+ context 'when query cache is not enabled' do
32
+ before do
33
+ Mongoid::QueryCache.enabled = false
34
+ end
35
+
36
+ it 'turns on the query cache within the block' do
37
+ expect(Mongoid::QueryCache.enabled?).to be false
38
+
39
+ Mongoid::QueryCache.cache do
40
+ expect(Mongoid::QueryCache.enabled?).to be true
41
+ end
42
+
43
+ expect(Mongoid::QueryCache.enabled?).to be false
44
+ end
45
+ end
46
+
47
+ context 'when query cache is enabled' do
48
+ before do
49
+ Mongoid::QueryCache.enabled = true
50
+ end
51
+
52
+ it 'keeps the query cache enabled within the block' do
53
+ expect(Mongoid::QueryCache.enabled?).to be true
54
+
55
+ Mongoid::QueryCache.cache do
56
+ expect(Mongoid::QueryCache.enabled?).to be true
57
+ end
58
+
59
+ expect(Mongoid::QueryCache.enabled?).to be true
60
+ end
61
+ end
62
+
63
+ context 'nested inside #uncached' do
64
+ it 'turns on the query cache in the block' do
65
+ Mongoid::QueryCache.uncached do
66
+ expect(Mongoid::QueryCache.enabled?).to be false
67
+
68
+ Mongoid::QueryCache.cache do
69
+ expect(Mongoid::QueryCache.enabled?).to be true
70
+ end
71
+
72
+ expect(Mongoid::QueryCache.enabled?).to be false
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'with mongoid query cache' do
79
+ max_driver_version '2.13'
80
+
81
+ context 'when query cache is not enabled' do
82
+ before do
83
+ Mongoid::QueryCache.enabled = false
84
+ end
85
+
86
+ it 'turns on the query cache within the block' do
87
+ expect(Mongoid::QueryCache.enabled?).to be false
88
+
89
+ Mongoid::QueryCache.cache do
90
+ expect(Mongoid::QueryCache.enabled?).to be true
91
+ end
92
+
93
+ expect(Mongoid::QueryCache.enabled?).to be false
94
+ end
95
+ end
96
+
97
+ context 'when query cache is enabled' do
98
+ before do
99
+ Mongoid::QueryCache.enabled = true
100
+ end
101
+
102
+ it 'keeps the query cache enabled within the block' do
103
+ expect(Mongoid::QueryCache.enabled?).to be true
104
+
105
+ Mongoid::QueryCache.cache do
106
+ expect(Mongoid::QueryCache.enabled?).to be true
107
+ end
108
+
109
+ expect(Mongoid::QueryCache.enabled?).to be true
110
+ end
111
+ end
112
+
113
+ context 'nested inside #uncached' do
114
+ it 'turns on the query cache in the block' do
115
+ Mongoid::QueryCache.uncached do
116
+ expect(Mongoid::QueryCache.enabled?).to be false
117
+
118
+ Mongoid::QueryCache.cache do
119
+ expect(Mongoid::QueryCache.enabled?).to be true
120
+ end
121
+
122
+ expect(Mongoid::QueryCache.enabled?).to be false
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#uncached' do
130
+ context 'with driver query cache' do
131
+ min_driver_version '2.14'
132
+
133
+ context 'when query cache is not enabled' do
134
+ before do
135
+ Mongoid::QueryCache.enabled = false
136
+ end
137
+
138
+ it 'keeps the query cache turned off within the block' do
139
+ expect(Mongoid::QueryCache.enabled?).to be false
140
+
141
+ Mongoid::QueryCache.uncached do
142
+ expect(Mongoid::QueryCache.enabled?).to be false
143
+ end
144
+
145
+ expect(Mongoid::QueryCache.enabled?).to be false
146
+ end
147
+ end
148
+
149
+ context 'when query cache is enabled' do
150
+ before do
151
+ Mongoid::QueryCache.enabled = true
152
+ end
153
+
154
+ it 'turns off the query cache within the block' do
155
+ expect(Mongoid::QueryCache.enabled?).to be true
156
+
157
+ Mongoid::QueryCache.uncached do
158
+ expect(Mongoid::QueryCache.enabled?).to be false
159
+ end
160
+
161
+ expect(Mongoid::QueryCache.enabled?).to be true
162
+ end
163
+ end
164
+
165
+ context 'nested inside #cache' do
166
+ it 'turns on the query cache in the block' do
167
+ Mongoid::QueryCache.cache do
168
+ expect(Mongoid::QueryCache.enabled?).to be true
169
+
170
+ Mongoid::QueryCache.uncached do
171
+ expect(Mongoid::QueryCache.enabled?).to be false
172
+ end
173
+
174
+ expect(Mongoid::QueryCache.enabled?).to be true
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ context 'with mongoid query cache' do
181
+ max_driver_version '2.13'
182
+
183
+ context 'when query cache is not enabled' do
184
+ before do
185
+ Mongoid::QueryCache.enabled = false
186
+ end
187
+
188
+ it 'keeps the query cache turned off within the block' do
189
+ expect(Mongoid::QueryCache.enabled?).to be false
190
+
191
+ Mongoid::QueryCache.uncached do
192
+ expect(Mongoid::QueryCache.enabled?).to be false
193
+ end
194
+
195
+ expect(Mongoid::QueryCache.enabled?).to be false
196
+ end
197
+ end
198
+
199
+ context 'when query cache is enabled' do
200
+ before do
201
+ Mongoid::QueryCache.enabled = true
202
+ end
203
+
204
+ it 'turns off the query cache within the block' do
205
+ expect(Mongoid::QueryCache.enabled?).to be true
206
+
207
+ Mongoid::QueryCache.uncached do
208
+ expect(Mongoid::QueryCache.enabled?).to be false
209
+ end
210
+
211
+ expect(Mongoid::QueryCache.enabled?).to be true
212
+ end
213
+ end
214
+
215
+ context 'nested inside #cache' do
216
+ it 'turns on the query cache in the block' do
217
+ Mongoid::QueryCache.cache do
218
+ expect(Mongoid::QueryCache.enabled?).to be true
219
+
220
+ Mongoid::QueryCache.uncached do
221
+ expect(Mongoid::QueryCache.enabled?).to be false
222
+ end
223
+
224
+ expect(Mongoid::QueryCache.enabled?).to be true
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+
13
231
  context 'when iterating over objects sharing the same base' do
14
232
 
15
233
  let(:server) do
@@ -85,6 +303,111 @@ describe Mongoid::QueryCache do
85
303
  end
86
304
  end
87
305
 
306
+ context 'when driver query cache exists' do
307
+ min_driver_version '2.14'
308
+
309
+ before do
310
+ Band.all.to_a
311
+ Band.create!
312
+ end
313
+
314
+ it 'recognizes the driver query cache' do
315
+ expect(defined?(Mongo::QueryCache)).to_not be_nil
316
+ end
317
+
318
+ context 'when query cache enabled' do
319
+
320
+ it 'uses the driver query cache' do
321
+ expect(Mongo::QueryCache).to receive(:enabled=).and_call_original
322
+ Mongoid::QueryCache.enabled = true
323
+
324
+ expect(Mongoid::QueryCache.enabled?).to be(true)
325
+ expect(Mongo::QueryCache.enabled?).to be(true)
326
+ end
327
+ end
328
+
329
+ context 'when query cache disabled' do
330
+
331
+ it 'uses the driver query cache' do
332
+ expect(Mongo::QueryCache).to receive(:enabled=).and_call_original
333
+ Mongoid::QueryCache.enabled = false
334
+
335
+ expect(Mongoid::QueryCache.enabled?).to be(false)
336
+ expect(Mongo::QueryCache.enabled?).to be(false)
337
+ end
338
+ end
339
+
340
+ context 'when block is cached' do
341
+
342
+ before do
343
+ Mongoid::QueryCache.enabled = false
344
+ end
345
+
346
+ it 'uses the driver query cache' do
347
+ expect(Mongo::QueryCache).to receive(:cache).and_call_original
348
+ Mongoid::QueryCache.cache do
349
+ expect(Mongo::QueryCache).to receive(:enabled?).exactly(2).and_call_original
350
+ expect(Mongoid::QueryCache.enabled?).to be(true)
351
+ expect(Mongo::QueryCache.enabled?).to be(true)
352
+ end
353
+ end
354
+ end
355
+
356
+ context 'when block is uncached' do
357
+
358
+ before do
359
+ Mongoid::QueryCache.enabled = true
360
+ end
361
+
362
+ it 'uses the driver query cache' do
363
+ expect(Mongo::QueryCache).to receive(:uncached).and_call_original
364
+ Mongoid::QueryCache.uncached do
365
+ expect(Mongo::QueryCache).to receive(:enabled?).exactly(2).and_call_original
366
+ expect(Mongoid::QueryCache.enabled?).to be(false)
367
+ expect(Mongo::QueryCache.enabled?).to be(false)
368
+ end
369
+ end
370
+ end
371
+
372
+ context 'when clear_cache is used' do
373
+
374
+ before do
375
+ Band.all.to_a
376
+ end
377
+
378
+ it 'requires Mongoid to query again' do
379
+ expect_no_queries do
380
+ Band.all.to_a
381
+ end
382
+
383
+ Mongoid::QueryCache.clear_cache
384
+
385
+ expect_query(1) do
386
+ Band.all.to_a
387
+ end
388
+ end
389
+ end
390
+
391
+ context 'when query cache used and cleared' do
392
+ it 'uses the driver query cache' do
393
+ expect(Mongo::QueryCache).to receive(:set).once.and_call_original
394
+
395
+ expect_query(1) do
396
+ Band.all.to_a
397
+ Band.all.to_a
398
+ end
399
+ end
400
+ end
401
+ end
402
+
403
+ context 'when drivers query cache does not exist' do
404
+ max_driver_version '2.13'
405
+
406
+ it 'does not recognize the driver query cache' do
407
+ expect(defined?(Mongo::QueryCache)).to be_nil
408
+ end
409
+ end
410
+
88
411
  context "when querying for a single document" do
89
412
 
90
413
  [ :first, :one, :last ].each do |method|
@@ -134,24 +457,81 @@ describe Mongoid::QueryCache do
134
457
  end
135
458
 
136
459
  it 'returns all documents' do
137
- expect(Person.all.to_a.count).to eq(3)
138
- Person.first
139
- expect(Person.all.to_a.count).to eq(3)
460
+ # Mongoid adds a sort by _id to the Person.first call, which is why
461
+ # these commands issue two queries instead of one.
462
+ expect_query(2) do
463
+ expect(Person.all.to_a.count).to eq(3)
464
+ Person.first
465
+ expect(Person.all.to_a.count).to eq(3)
466
+ end
467
+ end
468
+
469
+ it 'caches the query when order is specified' do
470
+ expect_query(1) do
471
+ expect(Person.order(_id: 1).all.to_a.count).to eq(3)
472
+ Person.first
473
+ expect(Person.order(_id: 1).all.to_a.count).to eq(3)
474
+ end
140
475
  end
141
476
 
142
477
  context 'with conditions specified' do
143
478
  it 'returns all documents' do
144
- expect(Person.gt(age: 0).to_a.count).to eq(3)
145
- Person.gt(age: 0).first
146
- expect(Person.gt(age: 0).to_a.count).to eq(3)
479
+ # Mongoid adds a sort by _id to the Person.first call, which is why
480
+ # these commands issue two queries instead of one.
481
+ expect_query(2) do
482
+ expect(Person.gt(age: 0).to_a.count).to eq(3)
483
+ Person.gt(age: 0).first
484
+ expect(Person.gt(age: 0).to_a.count).to eq(3)
485
+ end
486
+ end
487
+
488
+ it 'caches the query when order is specified' do
489
+ expect_query(1) do
490
+ expect(Person.order(_id: 1).gt(age: 0).to_a.count).to eq(3)
491
+ Person.gt(age: 0).first
492
+ expect(Person.order(_id: 1).gt(age: 0).to_a.count).to eq(3)
493
+ end
147
494
  end
148
495
  end
149
496
 
150
497
  context 'with order specified' do
151
498
  it 'returns all documents' do
152
- expect(Person.order_by(name: 1).to_a.count).to eq(3)
153
- Person.order_by(name: 1).first
154
- expect(Person.order_by(name: 1).to_a.count).to eq(3)
499
+ expect_query(1) do
500
+ expect(Person.order_by(name: 1).to_a.count).to eq(3)
501
+ Person.order_by(name: 1).first
502
+ expect(Person.order_by(name: 1).to_a.count).to eq(3)
503
+ end
504
+ end
505
+ end
506
+ end
507
+
508
+ context 'when using a block API' do
509
+ before do
510
+ Band.destroy_all
511
+ 5.times { Band.create }
512
+ end
513
+
514
+ context '#any? with no block' do
515
+ it 'doesn\'t leak sessions' do
516
+ Band.all.any?
517
+ end
518
+ end
519
+
520
+ context '#all? with no block' do
521
+ it 'doesn\'t leak sessions' do
522
+ Band.all.all?
523
+ end
524
+ end
525
+
526
+ context '#none? with no block' do
527
+ it 'doesn\'t leak sessions' do
528
+ Band.all.none?
529
+ end
530
+ end
531
+
532
+ context '#one? with no block' do
533
+ it 'doesn\'t leak sessions' do
534
+ Band.all.one?
155
535
  end
156
536
  end
157
537
  end
@@ -183,7 +563,8 @@ describe Mongoid::QueryCache do
183
563
  end
184
564
  end
185
565
 
186
- context 'when the first query has a collation', if: collation_supported? do
566
+ context 'when the first query has a collation' do
567
+ min_server_version '3.4'
187
568
 
188
569
  before do
189
570
  Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
@@ -224,6 +605,10 @@ describe Mongoid::QueryCache do
224
605
  end
225
606
 
226
607
  before do
608
+ 10.times do |i|
609
+ game.ratings << Rating.create!(value: i+1)
610
+ end
611
+
227
612
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
228
613
  end
229
614
 
@@ -231,27 +616,54 @@ describe Mongoid::QueryCache do
231
616
 
232
617
  it "uses the cache" do
233
618
  expect_no_queries do
234
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
619
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
620
+ expect(result.length).to eq(2)
621
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
235
622
  end
236
623
  end
237
624
  end
238
625
  end
239
626
 
240
627
  context "when the first query has a limit" do
241
-
242
628
  let(:game) do
243
629
  Game.create!(name: "2048")
244
630
  end
245
631
 
246
632
  before do
633
+ 10.times do |i|
634
+ game.ratings << Rating.create!(value: i+1)
635
+ end
636
+
247
637
  game.ratings.where(:value.gt => 5).limit(3).asc(:id).all.to_a
248
638
  end
249
639
 
250
640
  context "when the next query has a limit" do
641
+ # Server versions older than 3.2 also perform a killCursors operation,
642
+ # which causes this test to fail.
643
+ min_server_version '3.2'
644
+
645
+ context 'with driver query cache' do
646
+ min_driver_version '2.14'
647
+
648
+ # The driver query cache re-uses results with a larger limit
649
+ it 'does not query again' do
650
+ expect_no_queries do
651
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
652
+ expect(result.length).to eq(2)
653
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
654
+ end
655
+ end
656
+ end
251
657
 
252
- it "queries again" do
253
- expect_query(1) do
254
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
658
+ context 'with mongoid query cache' do
659
+ max_driver_version '2.13'
660
+
661
+ it 'queries again' do
662
+ expect_query(1) do
663
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
664
+ expect(result.length).to eq(2)
665
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
666
+ end
255
667
  end
256
668
  end
257
669
  end
@@ -260,7 +672,9 @@ describe Mongoid::QueryCache do
260
672
 
261
673
  it "queries again" do
262
674
  expect_query(1) do
263
- game.ratings.where(:value.gt => 5).asc(:id).to_a
675
+ result = game.ratings.where(:value.gt => 5).asc(:id).to_a
676
+ expect(result.length).to eq(5)
677
+ expect(result.map { |r| r['value'] }).to eq([6, 7, 8, 9, 10])
264
678
  end
265
679
  end
266
680
  end
@@ -273,21 +687,34 @@ describe Mongoid::QueryCache do
273
687
  end
274
688
 
275
689
  before do
690
+ 10.times do |i|
691
+ game.ratings << Rating.create!(value: i+1)
692
+ end
693
+
276
694
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
277
695
  end
278
696
 
279
697
  it "does not query again" do
280
698
  expect_no_queries do
281
- game.ratings.where(:value.gt => 5).asc(:id).first
699
+ result = game.ratings.where(:value.gt => 5).asc(:id).first
700
+ expect(result['value']).to eq(6)
282
701
  end
283
702
  end
284
703
  end
285
704
 
286
705
  context "when limiting the result" do
706
+ before do
707
+ Band.destroy_all
708
+
709
+ 5.times { |i| Band.create!(name: "Band #{i}") }
710
+ Band.all.to_a
711
+ end
287
712
 
288
713
  it "does not query again" do
289
714
  expect_query(0) do
290
- Band.limit(2).all.to_a
715
+ result = Band.limit(2).all.to_a
716
+ expect(result.length).to eq(2)
717
+ expect(result.map { |r| r["name"] }).to eq(["Band 0", "Band 1"])
291
718
  end
292
719
  end
293
720
  end
@@ -295,12 +722,17 @@ describe Mongoid::QueryCache do
295
722
  context "when specifying a different skip value" do
296
723
 
297
724
  before do
725
+ Band.destroy_all
726
+
727
+ 5.times { |i| Band.create!(name: "Band #{i}") }
298
728
  Band.limit(2).skip(1).all.to_a
299
729
  end
300
730
 
301
731
  it "queries again" do
302
732
  expect_query(1) do
303
- Band.limit(2).skip(3).all.to_a
733
+ result = Band.limit(2).skip(3).all.to_a
734
+ expect(result.length).to eq(2)
735
+ expect(result.map { |r| r["name"] }).to eq(["Band 3", "Band 4"])
304
736
  end
305
737
  end
306
738
  end
@@ -336,6 +768,25 @@ describe Mongoid::QueryCache do
336
768
  end
337
769
  end
338
770
 
771
+ context 'when querying colleciton larger than the batch size' do
772
+ before do
773
+ Band.destroy_all
774
+ 101.times { |i| Band.create!(_id: i) }
775
+ end
776
+
777
+ it 'does not raise an exception when querying multiple times' do
778
+ expect do
779
+ results1 = Band.all.to_a
780
+ expect(results1.length).to eq(101)
781
+ expect(results1.map { |band| band["_id"] }).to eq([*0..100])
782
+
783
+ results2 = Band.all.to_a
784
+ expect(results2.length).to eq(101)
785
+ expect(results2.map { |band| band["_id"] }).to eq([*0..100])
786
+ end.not_to raise_error
787
+ end
788
+ end
789
+
339
790
  context "when query caching is enabled and the batch_size is set" do
340
791
 
341
792
  around(:each) do |example|
@@ -470,8 +921,10 @@ describe Mongoid::QueryCache do
470
921
  end
471
922
  end
472
923
 
473
- it "returns the same count of objects when using #pluck" do
474
- expect(Band.pluck(:name).length).to eq(99)
924
+ it "returns the same count of objects when using #pluck but doesn't cache" do
925
+ expect_query(1) do
926
+ expect(Band.pluck(:name).length).to eq(99)
927
+ end
475
928
  end
476
929
  end
477
930
  end
@@ -489,20 +942,36 @@ describe Mongoid::QueryCache do
489
942
  Mongoid::QueryCache.enabled = true
490
943
  10.times { Band.create! }
491
944
 
492
- Band.batch_size(4).all.any?
945
+ Band.batch_size(4).to_a
493
946
  end
494
947
 
495
- it 'does not cache the result' do
496
- expect(Band.all.map(&:id).size).to eq(10)
497
- end
948
+ context 'with driver query cache' do
949
+ min_driver_version '2.14'
498
950
 
499
- context 'when a batch size smaller than the result set is specified' do
500
- let(:batch_size) do
501
- 4
951
+ # The driver query cache caches multi-batch cursors
952
+ it 'does cache the result' do
953
+ expect_no_queries do
954
+ expect(Band.all.map(&:id).size).to eq(10)
955
+ end
502
956
  end
957
+ end
958
+
959
+ context 'with mongoid query cache' do
960
+ max_driver_version '2.13'
503
961
 
504
962
  it 'does not cache the result' do
505
- expect(Band.batch_size(batch_size).all.map(&:id).size).to eq(10)
963
+ expect_query(1) do
964
+ expect(Band.all.map(&:id).size).to eq(10)
965
+ end
966
+ end
967
+ end
968
+ end
969
+
970
+ context 'when storing in system collection' do
971
+ it 'does not cache the query' do
972
+ expect_query(2) do
973
+ SystemRole.all.to_a
974
+ SystemRole.all.to_a
506
975
  end
507
976
  end
508
977
  end