mongoid_rails4 4.0.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 (659) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3213 -0
  3. data/LICENSE +20 -0
  4. data/README.md +62 -0
  5. data/Rakefile +35 -0
  6. data/lib/config/locales/en.yml +448 -0
  7. data/lib/mongoid.rb +104 -0
  8. data/lib/mongoid/atomic.rb +384 -0
  9. data/lib/mongoid/atomic/modifiers.rb +317 -0
  10. data/lib/mongoid/atomic/paths.rb +3 -0
  11. data/lib/mongoid/atomic/paths/embedded.rb +28 -0
  12. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  13. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  14. data/lib/mongoid/atomic/paths/root.rb +39 -0
  15. data/lib/mongoid/attributes.rb +284 -0
  16. data/lib/mongoid/attributes/dynamic.rb +154 -0
  17. data/lib/mongoid/attributes/nested.rb +82 -0
  18. data/lib/mongoid/attributes/processing.rb +147 -0
  19. data/lib/mongoid/attributes/readonly.rb +56 -0
  20. data/lib/mongoid/changeable.rb +379 -0
  21. data/lib/mongoid/composable.rb +104 -0
  22. data/lib/mongoid/config.rb +263 -0
  23. data/lib/mongoid/config/environment.rb +44 -0
  24. data/lib/mongoid/config/options.rb +74 -0
  25. data/lib/mongoid/config/validators.rb +3 -0
  26. data/lib/mongoid/config/validators/option.rb +25 -0
  27. data/lib/mongoid/config/validators/session.rb +140 -0
  28. data/lib/mongoid/contextual.rb +54 -0
  29. data/lib/mongoid/contextual/aggregable/memory.rb +109 -0
  30. data/lib/mongoid/contextual/aggregable/mongo.rb +147 -0
  31. data/lib/mongoid/contextual/atomic.rb +180 -0
  32. data/lib/mongoid/contextual/command.rb +61 -0
  33. data/lib/mongoid/contextual/eager.rb +158 -0
  34. data/lib/mongoid/contextual/find_and_modify.rb +69 -0
  35. data/lib/mongoid/contextual/geo_near.rb +238 -0
  36. data/lib/mongoid/contextual/map_reduce.rb +324 -0
  37. data/lib/mongoid/contextual/memory.rb +440 -0
  38. data/lib/mongoid/contextual/mongo.rb +676 -0
  39. data/lib/mongoid/contextual/queryable.rb +25 -0
  40. data/lib/mongoid/contextual/text_search.rb +180 -0
  41. data/lib/mongoid/copyable.rb +67 -0
  42. data/lib/mongoid/criteria.rb +562 -0
  43. data/lib/mongoid/criteria/findable.rb +179 -0
  44. data/lib/mongoid/criteria/inspectable.rb +25 -0
  45. data/lib/mongoid/criteria/marshalable.rb +50 -0
  46. data/lib/mongoid/criteria/modifiable.rb +189 -0
  47. data/lib/mongoid/criteria/scopable.rb +158 -0
  48. data/lib/mongoid/document.rb +361 -0
  49. data/lib/mongoid/equality.rb +66 -0
  50. data/lib/mongoid/errors.rb +40 -0
  51. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  52. data/lib/mongoid/errors/callback.rb +25 -0
  53. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  54. data/lib/mongoid/errors/document_not_found.rb +111 -0
  55. data/lib/mongoid/errors/eager_load.rb +22 -0
  56. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  57. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  58. data/lib/mongoid/errors/invalid_field.rb +64 -0
  59. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  60. data/lib/mongoid/errors/invalid_find.rb +19 -0
  61. data/lib/mongoid/errors/invalid_includes.rb +32 -0
  62. data/lib/mongoid/errors/invalid_index.rb +28 -0
  63. data/lib/mongoid/errors/invalid_options.rb +28 -0
  64. data/lib/mongoid/errors/invalid_path.rb +21 -0
  65. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  66. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  67. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  68. data/lib/mongoid/errors/invalid_time.rb +22 -0
  69. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  70. data/lib/mongoid/errors/mixed_relations.rb +32 -0
  71. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  72. data/lib/mongoid/errors/mongoid_error.rb +92 -0
  73. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  74. data/lib/mongoid/errors/no_default_session.rb +23 -0
  75. data/lib/mongoid/errors/no_environment.rb +19 -0
  76. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  77. data/lib/mongoid/errors/no_metadata.rb +21 -0
  78. data/lib/mongoid/errors/no_parent.rb +24 -0
  79. data/lib/mongoid/errors/no_session_config.rb +22 -0
  80. data/lib/mongoid/errors/no_session_database.rb +27 -0
  81. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  82. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  83. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  84. data/lib/mongoid/errors/scope_overwrite.rb +21 -0
  85. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  86. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  87. data/lib/mongoid/errors/unsaved_document.rb +19 -0
  88. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  89. data/lib/mongoid/errors/validations.rb +29 -0
  90. data/lib/mongoid/evolvable.rb +19 -0
  91. data/lib/mongoid/extensions.rb +35 -0
  92. data/lib/mongoid/extensions/array.rb +180 -0
  93. data/lib/mongoid/extensions/big_decimal.rb +69 -0
  94. data/lib/mongoid/extensions/boolean.rb +21 -0
  95. data/lib/mongoid/extensions/date.rb +77 -0
  96. data/lib/mongoid/extensions/date_time.rb +73 -0
  97. data/lib/mongoid/extensions/false_class.rb +38 -0
  98. data/lib/mongoid/extensions/float.rb +56 -0
  99. data/lib/mongoid/extensions/hash.rb +209 -0
  100. data/lib/mongoid/extensions/integer.rb +67 -0
  101. data/lib/mongoid/extensions/module.rb +28 -0
  102. data/lib/mongoid/extensions/nil_class.rb +33 -0
  103. data/lib/mongoid/extensions/object.rb +274 -0
  104. data/lib/mongoid/extensions/object_id.rb +54 -0
  105. data/lib/mongoid/extensions/range.rb +79 -0
  106. data/lib/mongoid/extensions/regexp.rb +27 -0
  107. data/lib/mongoid/extensions/set.rb +55 -0
  108. data/lib/mongoid/extensions/string.rb +199 -0
  109. data/lib/mongoid/extensions/symbol.rb +54 -0
  110. data/lib/mongoid/extensions/time.rb +88 -0
  111. data/lib/mongoid/extensions/time_with_zone.rb +56 -0
  112. data/lib/mongoid/extensions/true_class.rb +38 -0
  113. data/lib/mongoid/factory.rb +46 -0
  114. data/lib/mongoid/fields.rb +542 -0
  115. data/lib/mongoid/fields/foreign_key.rb +174 -0
  116. data/lib/mongoid/fields/localized.rb +73 -0
  117. data/lib/mongoid/fields/standard.rb +273 -0
  118. data/lib/mongoid/fields/validators.rb +2 -0
  119. data/lib/mongoid/fields/validators/macro.rb +92 -0
  120. data/lib/mongoid/findable.rb +133 -0
  121. data/lib/mongoid/identity_map.rb +163 -0
  122. data/lib/mongoid/indexable.rb +147 -0
  123. data/lib/mongoid/indexable/specification.rb +115 -0
  124. data/lib/mongoid/indexable/validators/options.rb +103 -0
  125. data/lib/mongoid/inspectable.rb +59 -0
  126. data/lib/mongoid/interceptable.rb +265 -0
  127. data/lib/mongoid/loggable.rb +69 -0
  128. data/lib/mongoid/matchable.rb +152 -0
  129. data/lib/mongoid/matchable/all.rb +27 -0
  130. data/lib/mongoid/matchable/and.rb +30 -0
  131. data/lib/mongoid/matchable/default.rb +72 -0
  132. data/lib/mongoid/matchable/exists.rb +23 -0
  133. data/lib/mongoid/matchable/gt.rb +21 -0
  134. data/lib/mongoid/matchable/gte.rb +21 -0
  135. data/lib/mongoid/matchable/in.rb +24 -0
  136. data/lib/mongoid/matchable/lt.rb +21 -0
  137. data/lib/mongoid/matchable/lte.rb +21 -0
  138. data/lib/mongoid/matchable/ne.rb +21 -0
  139. data/lib/mongoid/matchable/nin.rb +21 -0
  140. data/lib/mongoid/matchable/or.rb +33 -0
  141. data/lib/mongoid/matchable/size.rb +21 -0
  142. data/lib/mongoid/persistable.rb +207 -0
  143. data/lib/mongoid/persistable/creatable.rb +189 -0
  144. data/lib/mongoid/persistable/deletable.rb +149 -0
  145. data/lib/mongoid/persistable/destroyable.rb +55 -0
  146. data/lib/mongoid/persistable/incrementable.rb +36 -0
  147. data/lib/mongoid/persistable/logical.rb +38 -0
  148. data/lib/mongoid/persistable/poppable.rb +39 -0
  149. data/lib/mongoid/persistable/pullable.rb +55 -0
  150. data/lib/mongoid/persistable/pushable.rb +62 -0
  151. data/lib/mongoid/persistable/renamable.rb +35 -0
  152. data/lib/mongoid/persistable/savable.rb +52 -0
  153. data/lib/mongoid/persistable/settable.rb +33 -0
  154. data/lib/mongoid/persistable/unsettable.rb +36 -0
  155. data/lib/mongoid/persistable/updatable.rb +151 -0
  156. data/lib/mongoid/persistable/upsertable.rb +55 -0
  157. data/lib/mongoid/positional.rb +71 -0
  158. data/lib/mongoid/railtie.rb +156 -0
  159. data/lib/mongoid/railties/database.rake +97 -0
  160. data/lib/mongoid/railties/document.rb +12 -0
  161. data/lib/mongoid/relations.rb +162 -0
  162. data/lib/mongoid/relations/accessors.rb +299 -0
  163. data/lib/mongoid/relations/auto_save.rb +106 -0
  164. data/lib/mongoid/relations/binding.rb +218 -0
  165. data/lib/mongoid/relations/bindings.rb +9 -0
  166. data/lib/mongoid/relations/bindings/embedded/in.rb +63 -0
  167. data/lib/mongoid/relations/bindings/embedded/many.rb +50 -0
  168. data/lib/mongoid/relations/bindings/embedded/one.rb +55 -0
  169. data/lib/mongoid/relations/bindings/referenced/in.rb +65 -0
  170. data/lib/mongoid/relations/bindings/referenced/many.rb +42 -0
  171. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +67 -0
  172. data/lib/mongoid/relations/bindings/referenced/one.rb +44 -0
  173. data/lib/mongoid/relations/builder.rb +57 -0
  174. data/lib/mongoid/relations/builders.rb +104 -0
  175. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  176. data/lib/mongoid/relations/builders/embedded/many.rb +36 -0
  177. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  178. data/lib/mongoid/relations/builders/nested_attributes/many.rb +174 -0
  179. data/lib/mongoid/relations/builders/nested_attributes/one.rb +126 -0
  180. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  181. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  182. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +40 -0
  183. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  184. data/lib/mongoid/relations/cascading.rb +56 -0
  185. data/lib/mongoid/relations/cascading/delete.rb +44 -0
  186. data/lib/mongoid/relations/cascading/destroy.rb +43 -0
  187. data/lib/mongoid/relations/cascading/nullify.rb +35 -0
  188. data/lib/mongoid/relations/cascading/restrict.rb +39 -0
  189. data/lib/mongoid/relations/constraint.rb +49 -0
  190. data/lib/mongoid/relations/conversions.rb +34 -0
  191. data/lib/mongoid/relations/counter_cache.rb +105 -0
  192. data/lib/mongoid/relations/cyclic.rb +107 -0
  193. data/lib/mongoid/relations/embedded/batchable.rb +355 -0
  194. data/lib/mongoid/relations/embedded/in.rb +231 -0
  195. data/lib/mongoid/relations/embedded/many.rb +639 -0
  196. data/lib/mongoid/relations/embedded/one.rb +223 -0
  197. data/lib/mongoid/relations/macros.rb +356 -0
  198. data/lib/mongoid/relations/many.rb +208 -0
  199. data/lib/mongoid/relations/marshalable.rb +32 -0
  200. data/lib/mongoid/relations/metadata.rb +1174 -0
  201. data/lib/mongoid/relations/nested_builder.rb +74 -0
  202. data/lib/mongoid/relations/one.rb +48 -0
  203. data/lib/mongoid/relations/options.rb +48 -0
  204. data/lib/mongoid/relations/polymorphic.rb +39 -0
  205. data/lib/mongoid/relations/proxy.rb +270 -0
  206. data/lib/mongoid/relations/referenced/in.rb +297 -0
  207. data/lib/mongoid/relations/referenced/many.rb +787 -0
  208. data/lib/mongoid/relations/referenced/many_to_many.rb +486 -0
  209. data/lib/mongoid/relations/referenced/one.rb +290 -0
  210. data/lib/mongoid/relations/reflections.rb +62 -0
  211. data/lib/mongoid/relations/synchronization.rb +169 -0
  212. data/lib/mongoid/relations/targets.rb +2 -0
  213. data/lib/mongoid/relations/targets/enumerable.rb +473 -0
  214. data/lib/mongoid/relations/touchable.rb +94 -0
  215. data/lib/mongoid/reloadable.rb +95 -0
  216. data/lib/mongoid/scopable.rb +379 -0
  217. data/lib/mongoid/selectable.rb +59 -0
  218. data/lib/mongoid/serializable.rb +170 -0
  219. data/lib/mongoid/sessions.rb +330 -0
  220. data/lib/mongoid/sessions/factory.rb +129 -0
  221. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  222. data/lib/mongoid/sessions/options.rb +141 -0
  223. data/lib/mongoid/sessions/validators.rb +2 -0
  224. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  225. data/lib/mongoid/shardable.rb +65 -0
  226. data/lib/mongoid/state.rb +97 -0
  227. data/lib/mongoid/threaded.rb +383 -0
  228. data/lib/mongoid/threaded/lifecycle.rb +164 -0
  229. data/lib/mongoid/timestamps.rb +15 -0
  230. data/lib/mongoid/timestamps/created.rb +30 -0
  231. data/lib/mongoid/timestamps/created/short.rb +19 -0
  232. data/lib/mongoid/timestamps/short.rb +10 -0
  233. data/lib/mongoid/timestamps/updated.rb +39 -0
  234. data/lib/mongoid/timestamps/updated/short.rb +19 -0
  235. data/lib/mongoid/traversable.rb +192 -0
  236. data/lib/mongoid/unit_of_work.rb +61 -0
  237. data/lib/mongoid/validatable.rb +180 -0
  238. data/lib/mongoid/validatable/associated.rb +48 -0
  239. data/lib/mongoid/validatable/format.rb +20 -0
  240. data/lib/mongoid/validatable/length.rb +20 -0
  241. data/lib/mongoid/validatable/localizable.rb +30 -0
  242. data/lib/mongoid/validatable/macros.rb +94 -0
  243. data/lib/mongoid/validatable/presence.rb +86 -0
  244. data/lib/mongoid/validatable/queryable.rb +30 -0
  245. data/lib/mongoid/validatable/uniqueness.rb +330 -0
  246. data/lib/mongoid/version.rb +4 -0
  247. data/lib/rack/mongoid.rb +2 -0
  248. data/lib/rack/mongoid/middleware/identity_map.rb +39 -0
  249. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  250. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +76 -0
  251. data/lib/rails/generators/mongoid/model/model_generator.rb +25 -0
  252. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  253. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  254. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  255. data/lib/rails/generators/mongoid_generator.rb +65 -0
  256. data/lib/rails/mongoid.rb +180 -0
  257. data/lib/support/ruby_version.rb +26 -0
  258. data/spec/app/models/account.rb +28 -0
  259. data/spec/app/models/acolyte.rb +17 -0
  260. data/spec/app/models/actor.rb +18 -0
  261. data/spec/app/models/actress.rb +2 -0
  262. data/spec/app/models/address.rb +77 -0
  263. data/spec/app/models/address_component.rb +5 -0
  264. data/spec/app/models/address_number.rb +6 -0
  265. data/spec/app/models/agency.rb +5 -0
  266. data/spec/app/models/agent.rb +12 -0
  267. data/spec/app/models/album.rb +14 -0
  268. data/spec/app/models/alert.rb +5 -0
  269. data/spec/app/models/animal.rb +25 -0
  270. data/spec/app/models/answer.rb +4 -0
  271. data/spec/app/models/appointment.rb +7 -0
  272. data/spec/app/models/article.rb +10 -0
  273. data/spec/app/models/artist.rb +66 -0
  274. data/spec/app/models/artwork.rb +4 -0
  275. data/spec/app/models/audio.rb +5 -0
  276. data/spec/app/models/augmentation.rb +11 -0
  277. data/spec/app/models/author.rb +4 -0
  278. data/spec/app/models/band.rb +26 -0
  279. data/spec/app/models/bar.rb +10 -0
  280. data/spec/app/models/basic.rb +6 -0
  281. data/spec/app/models/bed.rb +1 -0
  282. data/spec/app/models/big_palette.rb +2 -0
  283. data/spec/app/models/birthday.rb +13 -0
  284. data/spec/app/models/book.rb +13 -0
  285. data/spec/app/models/breed.rb +4 -0
  286. data/spec/app/models/browser.rb +6 -0
  287. data/spec/app/models/building.rb +5 -0
  288. data/spec/app/models/building_address.rb +5 -0
  289. data/spec/app/models/bus.rb +7 -0
  290. data/spec/app/models/business.rb +5 -0
  291. data/spec/app/models/callback_recorder.rb +25 -0
  292. data/spec/app/models/callback_test.rb +9 -0
  293. data/spec/app/models/canvas.rb +25 -0
  294. data/spec/app/models/car.rb +1 -0
  295. data/spec/app/models/cat.rb +8 -0
  296. data/spec/app/models/category.rb +8 -0
  297. data/spec/app/models/child.rb +4 -0
  298. data/spec/app/models/child_doc.rb +22 -0
  299. data/spec/app/models/church.rb +4 -0
  300. data/spec/app/models/circle.rb +3 -0
  301. data/spec/app/models/circuit.rb +4 -0
  302. data/spec/app/models/circus.rb +7 -0
  303. data/spec/app/models/code.rb +5 -0
  304. data/spec/app/models/comment.rb +16 -0
  305. data/spec/app/models/contractor.rb +5 -0
  306. data/spec/app/models/cookie.rb +6 -0
  307. data/spec/app/models/country_code.rb +8 -0
  308. data/spec/app/models/definition.rb +7 -0
  309. data/spec/app/models/description.rb +11 -0
  310. data/spec/app/models/dictionary.rb +10 -0
  311. data/spec/app/models/division.rb +10 -0
  312. data/spec/app/models/doctor.rb +12 -0
  313. data/spec/app/models/dog.rb +7 -0
  314. data/spec/app/models/dokument.rb +5 -0
  315. data/spec/app/models/dragon.rb +4 -0
  316. data/spec/app/models/driver.rb +7 -0
  317. data/spec/app/models/drug.rb +6 -0
  318. data/spec/app/models/dungeon.rb +4 -0
  319. data/spec/app/models/email.rb +6 -0
  320. data/spec/app/models/employer.rb +5 -0
  321. data/spec/app/models/entry.rb +6 -0
  322. data/spec/app/models/eraser.rb +1 -0
  323. data/spec/app/models/event.rb +22 -0
  324. data/spec/app/models/exhibition.rb +4 -0
  325. data/spec/app/models/exhibitor.rb +5 -0
  326. data/spec/app/models/eye.rb +9 -0
  327. data/spec/app/models/eye_bowl.rb +9 -0
  328. data/spec/app/models/face.rb +8 -0
  329. data/spec/app/models/favorite.rb +6 -0
  330. data/spec/app/models/filesystem.rb +5 -0
  331. data/spec/app/models/fire_hydrant.rb +6 -0
  332. data/spec/app/models/firefox.rb +4 -0
  333. data/spec/app/models/fish.rb +7 -0
  334. data/spec/app/models/folder.rb +7 -0
  335. data/spec/app/models/folder_item.rb +9 -0
  336. data/spec/app/models/fruits.rb +28 -0
  337. data/spec/app/models/game.rb +19 -0
  338. data/spec/app/models/ghost.rb +7 -0
  339. data/spec/app/models/home.rb +4 -0
  340. data/spec/app/models/house.rb +6 -0
  341. data/spec/app/models/html_writer.rb +3 -0
  342. data/spec/app/models/image.rb +22 -0
  343. data/spec/app/models/implant.rb +16 -0
  344. data/spec/app/models/item.rb +8 -0
  345. data/spec/app/models/jar.rb +7 -0
  346. data/spec/app/models/label.rb +40 -0
  347. data/spec/app/models/language.rb +5 -0
  348. data/spec/app/models/lat_lng.rb +15 -0
  349. data/spec/app/models/league.rb +11 -0
  350. data/spec/app/models/learner.rb +2 -0
  351. data/spec/app/models/line_item.rb +6 -0
  352. data/spec/app/models/location.rb +8 -0
  353. data/spec/app/models/login.rb +8 -0
  354. data/spec/app/models/manufacturer.rb +7 -0
  355. data/spec/app/models/meat.rb +4 -0
  356. data/spec/app/models/membership.rb +4 -0
  357. data/spec/app/models/mixed_drink.rb +4 -0
  358. data/spec/app/models/movie.rb +13 -0
  359. data/spec/app/models/my_hash.rb +2 -0
  360. data/spec/app/models/name.rb +23 -0
  361. data/spec/app/models/node.rb +5 -0
  362. data/spec/app/models/note.rb +12 -0
  363. data/spec/app/models/ordered_post.rb +6 -0
  364. data/spec/app/models/ordered_preference.rb +6 -0
  365. data/spec/app/models/oscar.rb +15 -0
  366. data/spec/app/models/override.rb +16 -0
  367. data/spec/app/models/ownable.rb +6 -0
  368. data/spec/app/models/owner.rb +6 -0
  369. data/spec/app/models/pack.rb +3 -0
  370. data/spec/app/models/page.rb +5 -0
  371. data/spec/app/models/page_question.rb +4 -0
  372. data/spec/app/models/palette.rb +7 -0
  373. data/spec/app/models/parent.rb +5 -0
  374. data/spec/app/models/parent_doc.rb +6 -0
  375. data/spec/app/models/passport.rb +5 -0
  376. data/spec/app/models/patient.rb +9 -0
  377. data/spec/app/models/pdf_writer.rb +3 -0
  378. data/spec/app/models/pencil.rb +1 -0
  379. data/spec/app/models/person.rb +205 -0
  380. data/spec/app/models/pet.rb +23 -0
  381. data/spec/app/models/pet_owner.rb +6 -0
  382. data/spec/app/models/phone.rb +11 -0
  383. data/spec/app/models/pizza.rb +7 -0
  384. data/spec/app/models/player.rb +35 -0
  385. data/spec/app/models/post.rb +44 -0
  386. data/spec/app/models/powerup.rb +11 -0
  387. data/spec/app/models/preference.rb +9 -0
  388. data/spec/app/models/princess.rb +8 -0
  389. data/spec/app/models/product.rb +15 -0
  390. data/spec/app/models/profile.rb +5 -0
  391. data/spec/app/models/pronunciation.rb +5 -0
  392. data/spec/app/models/purchase.rb +4 -0
  393. data/spec/app/models/question.rb +8 -0
  394. data/spec/app/models/quiz.rb +7 -0
  395. data/spec/app/models/rating.rb +8 -0
  396. data/spec/app/models/record.rb +46 -0
  397. data/spec/app/models/registry.rb +4 -0
  398. data/spec/app/models/role.rb +7 -0
  399. data/spec/app/models/root_category.rb +4 -0
  400. data/spec/app/models/sandwich.rb +4 -0
  401. data/spec/app/models/scheduler.rb +7 -0
  402. data/spec/app/models/seo.rb +7 -0
  403. data/spec/app/models/series.rb +4 -0
  404. data/spec/app/models/server.rb +13 -0
  405. data/spec/app/models/service.rb +22 -0
  406. data/spec/app/models/shape.rb +12 -0
  407. data/spec/app/models/shelf.rb +5 -0
  408. data/spec/app/models/shipping_container.rb +5 -0
  409. data/spec/app/models/shipping_pack.rb +3 -0
  410. data/spec/app/models/shop.rb +6 -0
  411. data/spec/app/models/short_agent.rb +4 -0
  412. data/spec/app/models/short_quiz.rb +5 -0
  413. data/spec/app/models/slave.rb +6 -0
  414. data/spec/app/models/song.rb +8 -0
  415. data/spec/app/models/sound.rb +5 -0
  416. data/spec/app/models/square.rb +4 -0
  417. data/spec/app/models/strategy.rb +3 -0
  418. data/spec/app/models/sub_item.rb +3 -0
  419. data/spec/app/models/subscription.rb +4 -0
  420. data/spec/app/models/survey.rb +5 -0
  421. data/spec/app/models/symptom.rb +6 -0
  422. data/spec/app/models/tag.rb +8 -0
  423. data/spec/app/models/target.rb +5 -0
  424. data/spec/app/models/template.rb +5 -0
  425. data/spec/app/models/thing.rb +9 -0
  426. data/spec/app/models/title.rb +3 -0
  427. data/spec/app/models/tool.rb +8 -0
  428. data/spec/app/models/topping.rb +5 -0
  429. data/spec/app/models/track.rb +38 -0
  430. data/spec/app/models/translation.rb +5 -0
  431. data/spec/app/models/tree.rb +9 -0
  432. data/spec/app/models/truck.rb +3 -0
  433. data/spec/app/models/user.rb +21 -0
  434. data/spec/app/models/user_account.rb +10 -0
  435. data/spec/app/models/validation_callback.rb +10 -0
  436. data/spec/app/models/vehicle.rb +11 -0
  437. data/spec/app/models/version.rb +5 -0
  438. data/spec/app/models/vet_visit.rb +5 -0
  439. data/spec/app/models/video.rb +13 -0
  440. data/spec/app/models/weapon.rb +11 -0
  441. data/spec/app/models/wiki_page.rb +14 -0
  442. data/spec/app/models/word.rb +15 -0
  443. data/spec/app/models/word_origin.rb +11 -0
  444. data/spec/app/models/writer.rb +11 -0
  445. data/spec/config/mongoid.yml +38 -0
  446. data/spec/mongoid/atomic/modifiers_spec.rb +456 -0
  447. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +118 -0
  448. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +110 -0
  449. data/spec/mongoid/atomic/paths/root_spec.rb +48 -0
  450. data/spec/mongoid/atomic/paths_spec.rb +270 -0
  451. data/spec/mongoid/atomic_spec.rb +365 -0
  452. data/spec/mongoid/attributes/nested_spec.rb +4832 -0
  453. data/spec/mongoid/attributes/readonly_spec.rb +169 -0
  454. data/spec/mongoid/attributes_spec.rb +1412 -0
  455. data/spec/mongoid/changeable_spec.rb +1507 -0
  456. data/spec/mongoid/composable_spec.rb +24 -0
  457. data/spec/mongoid/config/environment_spec.rb +83 -0
  458. data/spec/mongoid/config/options_spec.rb +56 -0
  459. data/spec/mongoid/config_spec.rb +318 -0
  460. data/spec/mongoid/contextual/aggregable/memory_spec.rb +293 -0
  461. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +455 -0
  462. data/spec/mongoid/contextual/atomic_spec.rb +529 -0
  463. data/spec/mongoid/contextual/find_and_modify_spec.rb +220 -0
  464. data/spec/mongoid/contextual/geo_near_spec.rb +405 -0
  465. data/spec/mongoid/contextual/map_reduce_spec.rb +464 -0
  466. data/spec/mongoid/contextual/memory_spec.rb +1236 -0
  467. data/spec/mongoid/contextual/mongo_spec.rb +1843 -0
  468. data/spec/mongoid/contextual/text_search_spec.rb +207 -0
  469. data/spec/mongoid/copyable_spec.rb +393 -0
  470. data/spec/mongoid/criteria/findable_spec.rb +1189 -0
  471. data/spec/mongoid/criteria/inspectable_spec.rb +27 -0
  472. data/spec/mongoid/criteria/marshalable_spec.rb +28 -0
  473. data/spec/mongoid/criteria/modifiable_spec.rb +1063 -0
  474. data/spec/mongoid/criteria/scopable_spec.rb +391 -0
  475. data/spec/mongoid/criteria_spec.rb +3821 -0
  476. data/spec/mongoid/document_spec.rb +1205 -0
  477. data/spec/mongoid/equality_spec.rb +241 -0
  478. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +29 -0
  479. data/spec/mongoid/errors/callback_spec.rb +29 -0
  480. data/spec/mongoid/errors/delete_restriction_spec.rb +29 -0
  481. data/spec/mongoid/errors/document_not_found_spec.rb +104 -0
  482. data/spec/mongoid/errors/eager_load_spec.rb +29 -0
  483. data/spec/mongoid/errors/invalid_collection_spec.rb +36 -0
  484. data/spec/mongoid/errors/invalid_config_option_spec.rb +29 -0
  485. data/spec/mongoid/errors/invalid_field_option_spec.rb +29 -0
  486. data/spec/mongoid/errors/invalid_field_spec.rb +37 -0
  487. data/spec/mongoid/errors/invalid_find_spec.rb +29 -0
  488. data/spec/mongoid/errors/invalid_includes_spec.rb +40 -0
  489. data/spec/mongoid/errors/invalid_index_spec.rb +29 -0
  490. data/spec/mongoid/errors/invalid_options_spec.rb +29 -0
  491. data/spec/mongoid/errors/invalid_path_spec.rb +23 -0
  492. data/spec/mongoid/errors/invalid_scope_spec.rb +29 -0
  493. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +17 -0
  494. data/spec/mongoid/errors/invalid_storage_options_spec.rb +29 -0
  495. data/spec/mongoid/errors/invalid_time_spec.rb +29 -0
  496. data/spec/mongoid/errors/inverse_not_found_spec.rb +29 -0
  497. data/spec/mongoid/errors/mixed_relations_spec.rb +29 -0
  498. data/spec/mongoid/errors/mixed_session_configuration_spec.rb +29 -0
  499. data/spec/mongoid/errors/mongoid_error_spec.rb +48 -0
  500. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +29 -0
  501. data/spec/mongoid/errors/no_environment_spec.rb +29 -0
  502. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +29 -0
  503. data/spec/mongoid/errors/no_metadata_spec.rb +23 -0
  504. data/spec/mongoid/errors/no_parent_spec.rb +29 -0
  505. data/spec/mongoid/errors/no_session_config_spec.rb +29 -0
  506. data/spec/mongoid/errors/no_session_database_spec.rb +29 -0
  507. data/spec/mongoid/errors/no_session_hosts_spec.rb +29 -0
  508. data/spec/mongoid/errors/no_sessions_config_spec.rb +29 -0
  509. data/spec/mongoid/errors/readonly_attribute_spec.rb +29 -0
  510. data/spec/mongoid/errors/scope_overwrite_spec.rb +29 -0
  511. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +29 -0
  512. data/spec/mongoid/errors/unknown_attribute_spec.rb +29 -0
  513. data/spec/mongoid/errors/unsaved_document_spec.rb +37 -0
  514. data/spec/mongoid/errors/unsupported_javascript_spec.rb +29 -0
  515. data/spec/mongoid/errors/validations_spec.rb +45 -0
  516. data/spec/mongoid/extensions/array_spec.rb +638 -0
  517. data/spec/mongoid/extensions/big_decimal_spec.rb +104 -0
  518. data/spec/mongoid/extensions/binary_spec.rb +60 -0
  519. data/spec/mongoid/extensions/boolean_spec.rb +135 -0
  520. data/spec/mongoid/extensions/date_spec.rb +235 -0
  521. data/spec/mongoid/extensions/date_time_spec.rb +155 -0
  522. data/spec/mongoid/extensions/false_class_spec.rb +42 -0
  523. data/spec/mongoid/extensions/float_spec.rb +133 -0
  524. data/spec/mongoid/extensions/hash_spec.rb +333 -0
  525. data/spec/mongoid/extensions/integer_spec.rb +136 -0
  526. data/spec/mongoid/extensions/module_spec.rb +42 -0
  527. data/spec/mongoid/extensions/nil_class_spec.rb +11 -0
  528. data/spec/mongoid/extensions/object_id_spec.rb +946 -0
  529. data/spec/mongoid/extensions/object_spec.rb +292 -0
  530. data/spec/mongoid/extensions/range_spec.rb +105 -0
  531. data/spec/mongoid/extensions/regexp_spec.rb +47 -0
  532. data/spec/mongoid/extensions/set_spec.rb +33 -0
  533. data/spec/mongoid/extensions/string_spec.rb +357 -0
  534. data/spec/mongoid/extensions/symbol_spec.rb +76 -0
  535. data/spec/mongoid/extensions/time_spec.rb +467 -0
  536. data/spec/mongoid/extensions/time_with_zone_spec.rb +405 -0
  537. data/spec/mongoid/extensions/true_class_spec.rb +42 -0
  538. data/spec/mongoid/extensions_spec.rb +15 -0
  539. data/spec/mongoid/factory_spec.rb +185 -0
  540. data/spec/mongoid/fields/foreign_key_spec.rb +694 -0
  541. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +184 -0
  542. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +201 -0
  543. data/spec/mongoid/fields/localized_spec.rb +386 -0
  544. data/spec/mongoid/fields/standard_spec.rb +166 -0
  545. data/spec/mongoid/fields_spec.rb +1229 -0
  546. data/spec/mongoid/findable_spec.rb +342 -0
  547. data/spec/mongoid/identity_map_spec.rb +564 -0
  548. data/spec/mongoid/indexable/specification_spec.rb +87 -0
  549. data/spec/mongoid/indexable_spec.rb +504 -0
  550. data/spec/mongoid/inspectable_spec.rb +49 -0
  551. data/spec/mongoid/interceptable_spec.rb +1564 -0
  552. data/spec/mongoid/loggable_spec.rb +21 -0
  553. data/spec/mongoid/matchable/all_spec.rb +31 -0
  554. data/spec/mongoid/matchable/and_spec.rb +162 -0
  555. data/spec/mongoid/matchable/default_spec.rb +130 -0
  556. data/spec/mongoid/matchable/exists_spec.rb +57 -0
  557. data/spec/mongoid/matchable/gt_spec.rb +75 -0
  558. data/spec/mongoid/matchable/gte_spec.rb +74 -0
  559. data/spec/mongoid/matchable/in_spec.rb +25 -0
  560. data/spec/mongoid/matchable/lt_spec.rb +74 -0
  561. data/spec/mongoid/matchable/lte_spec.rb +74 -0
  562. data/spec/mongoid/matchable/ne_spec.rb +25 -0
  563. data/spec/mongoid/matchable/nin_spec.rb +25 -0
  564. data/spec/mongoid/matchable/or_spec.rb +106 -0
  565. data/spec/mongoid/matchable/size_spec.rb +25 -0
  566. data/spec/mongoid/matchable_spec.rb +532 -0
  567. data/spec/mongoid/persistable/creatable_spec.rb +512 -0
  568. data/spec/mongoid/persistable/deletable_spec.rb +205 -0
  569. data/spec/mongoid/persistable/destroyable_spec.rb +148 -0
  570. data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
  571. data/spec/mongoid/persistable/logical_spec.rb +143 -0
  572. data/spec/mongoid/persistable/poppable_spec.rb +115 -0
  573. data/spec/mongoid/persistable/pullable_spec.rb +228 -0
  574. data/spec/mongoid/persistable/pushable_spec.rb +258 -0
  575. data/spec/mongoid/persistable/renamable_spec.rb +135 -0
  576. data/spec/mongoid/persistable/savable_spec.rb +432 -0
  577. data/spec/mongoid/persistable/settable_spec.rb +139 -0
  578. data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
  579. data/spec/mongoid/persistable/updatable_spec.rb +522 -0
  580. data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
  581. data/spec/mongoid/persistable_spec.rb +206 -0
  582. data/spec/mongoid/positional_spec.rb +227 -0
  583. data/spec/mongoid/railties/document_spec.rb +24 -0
  584. data/spec/mongoid/relations/accessors_spec.rb +736 -0
  585. data/spec/mongoid/relations/auto_save_spec.rb +261 -0
  586. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +171 -0
  587. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +54 -0
  588. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +77 -0
  589. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +241 -0
  590. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +153 -0
  591. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +178 -0
  592. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +131 -0
  593. data/spec/mongoid/relations/builders/embedded/in_spec.rb +34 -0
  594. data/spec/mongoid/relations/builders/embedded/many_spec.rb +132 -0
  595. data/spec/mongoid/relations/builders/embedded/one_spec.rb +99 -0
  596. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +234 -0
  597. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +250 -0
  598. data/spec/mongoid/relations/builders/referenced/in_spec.rb +241 -0
  599. data/spec/mongoid/relations/builders/referenced/many_spec.rb +137 -0
  600. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +178 -0
  601. data/spec/mongoid/relations/builders/referenced/one_spec.rb +124 -0
  602. data/spec/mongoid/relations/builders_spec.rb +226 -0
  603. data/spec/mongoid/relations/cascading/delete_spec.rb +101 -0
  604. data/spec/mongoid/relations/cascading/destroy_spec.rb +47 -0
  605. data/spec/mongoid/relations/cascading/nullify_spec.rb +32 -0
  606. data/spec/mongoid/relations/cascading/restrict_spec.rb +68 -0
  607. data/spec/mongoid/relations/cascading_spec.rb +355 -0
  608. data/spec/mongoid/relations/constraint_spec.rb +74 -0
  609. data/spec/mongoid/relations/conversions_spec.rb +126 -0
  610. data/spec/mongoid/relations/counter_cache_spec.rb +205 -0
  611. data/spec/mongoid/relations/cyclic_spec.rb +156 -0
  612. data/spec/mongoid/relations/embedded/dirty_spec.rb +65 -0
  613. data/spec/mongoid/relations/embedded/in_spec.rb +579 -0
  614. data/spec/mongoid/relations/embedded/many_spec.rb +3781 -0
  615. data/spec/mongoid/relations/embedded/one_spec.rb +1014 -0
  616. data/spec/mongoid/relations/macros_spec.rb +613 -0
  617. data/spec/mongoid/relations/metadata_spec.rb +1917 -0
  618. data/spec/mongoid/relations/options_spec.rb +35 -0
  619. data/spec/mongoid/relations/polymorphic_spec.rb +128 -0
  620. data/spec/mongoid/relations/proxy_spec.rb +48 -0
  621. data/spec/mongoid/relations/referenced/in_spec.rb +1435 -0
  622. data/spec/mongoid/relations/referenced/many_spec.rb +3546 -0
  623. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +3556 -0
  624. data/spec/mongoid/relations/referenced/one_spec.rb +1289 -0
  625. data/spec/mongoid/relations/reflections_spec.rb +101 -0
  626. data/spec/mongoid/relations/synchronization_spec.rb +449 -0
  627. data/spec/mongoid/relations/targets/enumerable_spec.rb +1710 -0
  628. data/spec/mongoid/relations/touchable_spec.rb +296 -0
  629. data/spec/mongoid/relations_spec.rb +188 -0
  630. data/spec/mongoid/reloadable_spec.rb +305 -0
  631. data/spec/mongoid/scopable_spec.rb +926 -0
  632. data/spec/mongoid/selectable_spec.rb +134 -0
  633. data/spec/mongoid/serializable_spec.rb +862 -0
  634. data/spec/mongoid/sessions/factory_spec.rb +312 -0
  635. data/spec/mongoid/sessions/mongo_uri_spec.rb +103 -0
  636. data/spec/mongoid/sessions/options_spec.rb +71 -0
  637. data/spec/mongoid/sessions_spec.rb +1078 -0
  638. data/spec/mongoid/shardable_spec.rb +61 -0
  639. data/spec/mongoid/state_spec.rb +102 -0
  640. data/spec/mongoid/threaded_spec.rb +258 -0
  641. data/spec/mongoid/timestamps/created/short_spec.rb +51 -0
  642. data/spec/mongoid/timestamps/created_spec.rb +44 -0
  643. data/spec/mongoid/timestamps/updated/short_spec.rb +90 -0
  644. data/spec/mongoid/timestamps/updated_spec.rb +86 -0
  645. data/spec/mongoid/timestamps_spec.rb +112 -0
  646. data/spec/mongoid/traversable_spec.rb +244 -0
  647. data/spec/mongoid/unit_of_work_spec.rb +196 -0
  648. data/spec/mongoid/validatable/associated_spec.rb +183 -0
  649. data/spec/mongoid/validatable/format_spec.rb +83 -0
  650. data/spec/mongoid/validatable/length_spec.rb +119 -0
  651. data/spec/mongoid/validatable/numericality_spec.rb +30 -0
  652. data/spec/mongoid/validatable/presence_spec.rb +511 -0
  653. data/spec/mongoid/validatable/uniqueness_spec.rb +2305 -0
  654. data/spec/mongoid/validatable_spec.rb +309 -0
  655. data/spec/mongoid_spec.rb +74 -0
  656. data/spec/rack/mongoid/middleware/identity_map_spec.rb +72 -0
  657. data/spec/rails/mongoid_spec.rb +462 -0
  658. data/spec/spec_helper.rb +103 -0
  659. metadata +1159 -0
@@ -0,0 +1,391 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Scopable do
4
+
5
+ describe "#apply_default_scope" do
6
+
7
+ context "when the default scope has options" do
8
+
9
+ let(:scope) do
10
+ Band.skip(20)
11
+ end
12
+
13
+ before do
14
+ Band.default_scope scope
15
+ end
16
+
17
+ after do
18
+ Band.default_scoping = nil
19
+ end
20
+
21
+ let(:scoped) do
22
+ Band.all.tap do |criteria|
23
+ criteria.apply_default_scope
24
+ end
25
+ end
26
+
27
+ it "merges in the options" do
28
+ expect(scoped.options).to eq({ skip: 20 })
29
+ end
30
+
31
+ it "sets scoped to true" do
32
+ expect(scoped).to be_scoped
33
+ end
34
+ end
35
+
36
+ context "when the default scope has selection" do
37
+
38
+ let(:scope) do
39
+ Band.where(name: "Depeche Mode")
40
+ end
41
+
42
+ before do
43
+ Band.default_scope scope
44
+ end
45
+
46
+ after do
47
+ Band.default_scoping = nil
48
+ end
49
+
50
+ let(:scoped) do
51
+ Band.all.tap do |criteria|
52
+ criteria.apply_default_scope
53
+ end
54
+ end
55
+
56
+ it "merges in the options" do
57
+ expect(scoped.selector).to eq({ "name" => "Depeche Mode" })
58
+ end
59
+
60
+ it "sets scoped to true" do
61
+ expect(scoped).to be_scoped
62
+ end
63
+ end
64
+
65
+ context "when the default scope has inclusions" do
66
+
67
+ let(:scope) do
68
+ Band.includes(:records)
69
+ end
70
+
71
+ before do
72
+ Band.default_scope scope
73
+ end
74
+
75
+ after do
76
+ Band.default_scoping = nil
77
+ end
78
+
79
+ context "when merging with an empty criteria" do
80
+
81
+ let(:scoped) do
82
+ Band.all.tap do |criteria|
83
+ criteria.apply_default_scope
84
+ end
85
+ end
86
+
87
+ it "merges in the inclusions" do
88
+ expect(scoped.inclusions).to eq(
89
+ [ Band.relations["records"] ]
90
+ )
91
+ end
92
+
93
+ it "sets scoped to true" do
94
+ expect(scoped).to be_scoped
95
+ end
96
+ end
97
+
98
+ context "when merging with a criteria that has inclusions" do
99
+
100
+ let(:scoped) do
101
+ Band.includes(:label).tap do |criteria|
102
+ criteria.apply_default_scope
103
+ end
104
+ end
105
+
106
+ it "merges in the inclusions" do
107
+ expect(scoped.inclusions).to eq(
108
+ [ Band.relations["records"], Band.relations["label"] ]
109
+ )
110
+ end
111
+
112
+ it "sets scoped to true" do
113
+ expect(scoped).to be_scoped
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ describe "#remove_scoping" do
120
+
121
+ context "when the other has selection" do
122
+
123
+ let(:criteria) do
124
+ Band.where(name: "Depeche Mode")
125
+ end
126
+
127
+ before do
128
+ criteria.remove_scoping(criteria)
129
+ end
130
+
131
+ it "removes the selection" do
132
+ expect(criteria.selector).to be_empty
133
+ end
134
+ end
135
+
136
+ context "when the other has options" do
137
+
138
+ context "when both are options only" do
139
+
140
+ let(:criteria) do
141
+ Band.skip(10)
142
+ end
143
+
144
+ before do
145
+ criteria.remove_scoping(criteria)
146
+ end
147
+
148
+ it "removes the options" do
149
+ expect(criteria.options).to be_empty
150
+ end
151
+ end
152
+
153
+ context "when the criteria is selection only with nil" do
154
+
155
+ let(:criteria) do
156
+ Band.where(name: nil)
157
+ end
158
+
159
+ before do
160
+ criteria.remove_scoping(Band.asc(:_id))
161
+ end
162
+
163
+ it "removes the options" do
164
+ expect(criteria.options).to be_empty
165
+ end
166
+
167
+ it "does not remove the selector" do
168
+ expect(criteria.selector).to eq({ "name" => nil })
169
+ end
170
+ end
171
+ end
172
+
173
+ context "when the other has inclusions" do
174
+
175
+ let(:criteria) do
176
+ Band.includes(:records, :label)
177
+ end
178
+
179
+ let(:other) do
180
+ Band.includes(:label)
181
+ end
182
+
183
+ before do
184
+ criteria.remove_scoping(other)
185
+ end
186
+
187
+ it "removes the matching inclusions" do
188
+ expect(criteria.inclusions).to eq([ Band.relations["records"] ])
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "#scoped" do
194
+
195
+ let(:empty) do
196
+ Mongoid::Criteria.new(Band)
197
+ end
198
+
199
+ context "when no options are provided" do
200
+
201
+ let(:scoped) do
202
+ empty.scoped
203
+ end
204
+
205
+ it "returns a criteria" do
206
+ expect(scoped).to be_a(Mongoid::Criteria)
207
+ end
208
+
209
+ it "contains an empty selector" do
210
+ expect(scoped.selector).to be_empty
211
+ end
212
+
213
+ it "contains empty options" do
214
+ expect(scoped.options).to be_empty
215
+ end
216
+ end
217
+
218
+ context "when options are provided" do
219
+
220
+ let(:scoped) do
221
+ empty.scoped(skip: 10, limit: 10)
222
+ end
223
+
224
+ it "returns a criteria" do
225
+ expect(scoped).to be_a(Mongoid::Criteria)
226
+ end
227
+
228
+ it "contains an empty selector" do
229
+ expect(scoped.selector).to be_empty
230
+ end
231
+
232
+ it "contains the options" do
233
+ expect(scoped.options).to eq({ skip: 10, limit: 10 })
234
+ end
235
+ end
236
+
237
+ context "when a default scope exists" do
238
+
239
+ let(:criteria) do
240
+ Band.where(name: "Depeche Mode")
241
+ end
242
+
243
+ before do
244
+ Band.default_scope criteria
245
+ end
246
+
247
+ after do
248
+ Band.default_scoping = nil
249
+ end
250
+
251
+ let(:scoped) do
252
+ empty.scoped
253
+ end
254
+
255
+ it "allows the default scope to be added" do
256
+ expect(scoped.selector).to eq({ "name" => "Depeche Mode" })
257
+ end
258
+
259
+ it "flags as scoped" do
260
+ expect(scoped).to be_scoped
261
+ end
262
+
263
+ context "when chained after an unscoped criteria" do
264
+
265
+ let(:scoped) do
266
+ empty.unscoped.scoped
267
+ end
268
+
269
+ it "reapplies the default scope" do
270
+ expect(scoped.selector).to eq({ "name" => "Depeche Mode" })
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "#scoping_options" do
277
+
278
+ let(:criteria) do
279
+ Band.all
280
+ end
281
+
282
+ before do
283
+ criteria.scoping_options = true, false
284
+ end
285
+
286
+ it "returns the scoping options" do
287
+ expect(criteria.scoping_options).to eq([ true, false ])
288
+ end
289
+ end
290
+
291
+ describe "#scoping_options=" do
292
+
293
+ let(:criteria) do
294
+ Band.all
295
+ end
296
+
297
+ before do
298
+ criteria.scoping_options = true, true
299
+ end
300
+
301
+ it "sets the scoped flag" do
302
+ expect(criteria).to be_scoped
303
+ end
304
+
305
+ it "sets the unscoped flag" do
306
+ expect(criteria).to be_unscoped
307
+ end
308
+ end
309
+
310
+ describe ".unscoped" do
311
+
312
+ let(:empty) do
313
+ Mongoid::Criteria.new(Band)
314
+ end
315
+
316
+ let(:criteria) do
317
+ Band.where(name: "Depeche Mode")
318
+ end
319
+
320
+ before do
321
+ Band.default_scope criteria
322
+ end
323
+
324
+ after do
325
+ Band.default_scoping = nil
326
+ end
327
+
328
+ context "when called directly" do
329
+
330
+ let(:unscoped) do
331
+ empty.unscoped
332
+ end
333
+
334
+ it "removes the default scope from the criteria" do
335
+ expect(unscoped.selector).to be_empty
336
+ end
337
+
338
+ context "when chained after a scoped criteria" do
339
+
340
+ let(:unscoped) do
341
+ empty.scoped.unscoped
342
+ end
343
+
344
+ it "removes all scoping" do
345
+ expect(unscoped.selector).to be_empty
346
+ end
347
+ end
348
+ end
349
+
350
+ context "when used with a block" do
351
+
352
+ context "when a criteria is called in the block" do
353
+
354
+ it "does not allow default scoping to be added in the block" do
355
+ Band.unscoped do
356
+ expect(empty.skip(10).selector).to be_empty
357
+ end
358
+ end
359
+ end
360
+
361
+ context "when a call is made to scoped in the block" do
362
+
363
+ it "does not allow default scoping to be added in the block" do
364
+ Band.unscoped do
365
+ expect(empty.scoped.selector).to be_empty
366
+ end
367
+ end
368
+ end
369
+
370
+ context "when a named scope is called in the block" do
371
+
372
+ before do
373
+ Band.scope(:skipped, Band.skip(10))
374
+ end
375
+
376
+ after do
377
+ class << Band
378
+ undef_method :skipped
379
+ end
380
+ Band._declared_scopes.clear
381
+ end
382
+
383
+ it "does not allow the default scope to be applied" do
384
+ Band.unscoped do
385
+ expect(empty.skipped.selector).to be_empty
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end
391
+ end
@@ -0,0 +1,3821 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria do
4
+
5
+ describe "#==" do
6
+
7
+ let(:criteria) do
8
+ Band.where(name: "Depeche Mode")
9
+ end
10
+
11
+ context "when the other is a criteria" do
12
+
13
+ context "when the criteria are the same" do
14
+
15
+ let(:other) do
16
+ Band.where(name: "Depeche Mode")
17
+ end
18
+
19
+ it "returns true" do
20
+ expect(criteria).to eq(other)
21
+ end
22
+ end
23
+
24
+ context "when the criteria differ" do
25
+
26
+ let(:other) do
27
+ Band.where(name: "Tool")
28
+ end
29
+
30
+ it "returns false" do
31
+ expect(criteria).to_not eq(other)
32
+ end
33
+ end
34
+ end
35
+
36
+ context "when the other is an enumerable" do
37
+
38
+ context "when the entries are the same" do
39
+
40
+ let!(:band) do
41
+ Band.create(name: "Depeche Mode")
42
+ end
43
+
44
+ let(:other) do
45
+ [ band ]
46
+ end
47
+
48
+ it "returns true" do
49
+ expect(criteria).to eq(other)
50
+ end
51
+ end
52
+
53
+ context "when the entries are not the same" do
54
+
55
+ let!(:band) do
56
+ Band.create(name: "Depeche Mode")
57
+ end
58
+
59
+ let!(:other_band) do
60
+ Band.create(name: "Tool")
61
+ end
62
+
63
+ let(:other) do
64
+ [ other_band ]
65
+ end
66
+
67
+ it "returns false" do
68
+ expect(criteria).to_not eq(other)
69
+ end
70
+ end
71
+ end
72
+
73
+ context "when the other is neither a criteria or enumerable" do
74
+
75
+ it "returns false" do
76
+ expect(criteria).to_not eq("test")
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#===" do
82
+
83
+ context "when the other is a criteria" do
84
+
85
+ let(:other) do
86
+ Band.where(name: "Depeche Mode")
87
+ end
88
+
89
+ it "returns true" do
90
+ expect(described_class === other).to be_true
91
+ end
92
+ end
93
+
94
+ context "when the other is not a criteria" do
95
+
96
+ it "returns false" do
97
+ expect(described_class === []).to be_false
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#asc" do
103
+
104
+ let(:person) do
105
+ Person.create
106
+ end
107
+
108
+ context "when the documents are embedded" do
109
+
110
+ let!(:hobrecht) do
111
+ person.addresses.create(street: "hobrecht", name: "hobrecht")
112
+ end
113
+
114
+ let!(:friedel) do
115
+ person.addresses.create(street: "friedel", name: "friedel")
116
+ end
117
+
118
+ let!(:pfluger) do
119
+ person.addresses.create(street: "pfluger", name: "pfluger")
120
+ end
121
+
122
+ let(:criteria) do
123
+ person.addresses.asc(:name)
124
+ end
125
+
126
+ it "returns the sorted documents" do
127
+ expect(criteria).to eq([ friedel, hobrecht, pfluger ])
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#batch_size" do
133
+
134
+ let(:person) do
135
+ Person.create
136
+ end
137
+
138
+ let(:criteria) do
139
+ Person.batch_size(1000)
140
+ end
141
+
142
+ it "adds the batch size option" do
143
+ expect(criteria.options[:batch_size]).to eq(1000)
144
+ end
145
+
146
+ it "returns the correct documents" do
147
+ expect(criteria).to eq([ person ])
148
+ end
149
+ end
150
+
151
+ describe "#aggregates" do
152
+
153
+ context "when provided a single field" do
154
+
155
+ let!(:depeche) do
156
+ Band.create(name: "Depeche Mode", likes: 1000)
157
+ end
158
+
159
+ let!(:tool) do
160
+ Band.create(name: "Tool", likes: 500)
161
+ end
162
+
163
+ let(:criteria) do
164
+ Band.all
165
+ end
166
+
167
+ let(:aggregates) do
168
+ criteria.aggregates(:likes)
169
+ end
170
+
171
+ it "returns an avg" do
172
+ expect(aggregates["avg"]).to eq(750)
173
+ end
174
+
175
+ it "returns a count" do
176
+ expect(aggregates["count"]).to eq(2)
177
+ end
178
+
179
+ it "returns a max" do
180
+ expect(aggregates["max"]).to eq(1000)
181
+ end
182
+
183
+ it "returns a min" do
184
+ expect(aggregates["min"]).to eq(500)
185
+ end
186
+
187
+ it "returns a sum" do
188
+ expect(aggregates["sum"]).to eq(1500)
189
+ end
190
+ end
191
+ end
192
+
193
+ describe "#avg" do
194
+
195
+ context "when provided a single field" do
196
+
197
+ let!(:depeche) do
198
+ Band.create(name: "Depeche Mode", likes: 1000)
199
+ end
200
+
201
+ let!(:tool) do
202
+ Band.create(name: "Tool", likes: 500)
203
+ end
204
+
205
+ let(:criteria) do
206
+ Band.all
207
+ end
208
+
209
+ let(:avg) do
210
+ criteria.avg(:likes)
211
+ end
212
+
213
+ it "returns the avg of the provided field" do
214
+ expect(avg).to eq(750)
215
+ end
216
+ end
217
+ end
218
+
219
+ [ :all, :all_in ].each do |method|
220
+
221
+ describe "\##{method}" do
222
+
223
+ let!(:match) do
224
+ Band.create(genres: [ "electro", "dub" ])
225
+ end
226
+
227
+ let!(:non_match) do
228
+ Band.create(genres: [ "house" ])
229
+ end
230
+
231
+ let(:criteria) do
232
+ Band.send(method, genres: [ "electro", "dub" ])
233
+ end
234
+
235
+ it "returns the matching documents" do
236
+ expect(criteria).to eq([ match ])
237
+ end
238
+ end
239
+ end
240
+
241
+ [ :and, :all_of ].each do |method|
242
+
243
+ describe "\##{method}" do
244
+
245
+ let!(:match) do
246
+ Band.create(name: "Depeche Mode", genres: [ "electro" ])
247
+ end
248
+
249
+ let!(:non_match) do
250
+ Band.create(genres: [ "house" ])
251
+ end
252
+
253
+ let(:criteria) do
254
+ Band.send(method, { genres: "electro" }, { name: "Depeche Mode" })
255
+ end
256
+
257
+ it "returns the matching documents" do
258
+ expect(criteria).to eq([ match ])
259
+ end
260
+ end
261
+ end
262
+
263
+ describe "#as_json" do
264
+
265
+ let!(:band) do
266
+ Band.create(name: "Depeche Mode")
267
+ end
268
+
269
+ let(:criteria) do
270
+ Band.where(name: "Depeche Mode")
271
+ end
272
+
273
+ it "returns the criteria as a json hash" do
274
+ expect(criteria.as_json).to eq([ band.serializable_hash ])
275
+ end
276
+ end
277
+
278
+ describe "#between" do
279
+
280
+ let!(:match) do
281
+ Band.create(member_count: 3)
282
+ end
283
+
284
+ let!(:non_match) do
285
+ Band.create(member_count: 10)
286
+ end
287
+
288
+ let(:criteria) do
289
+ Band.between(member_count: 1..5)
290
+ end
291
+
292
+ it "returns the matching documents" do
293
+ expect(criteria).to eq([ match ])
294
+ end
295
+ end
296
+
297
+ [ :build, :new ].each do |method|
298
+
299
+ describe "##{method}" do
300
+
301
+ let(:criteria) do
302
+ Band.where(name: "Depeche Mode")
303
+ end
304
+
305
+ context "when provided valid attributes" do
306
+
307
+ let(:band) do
308
+ criteria.send(method, genres: [ "electro" ])
309
+ end
310
+
311
+ it "returns the new document" do
312
+ expect(band).to be_new_record
313
+ end
314
+
315
+ it "sets the criteria attributes" do
316
+ expect(band.name).to eq("Depeche Mode")
317
+ end
318
+
319
+ it "sets the attributes passed to build" do
320
+ expect(band.genres).to eq([ "electro" ])
321
+ end
322
+ end
323
+
324
+ context "when provided a block" do
325
+ context "when provided valid attributes" do
326
+ let(:band) do
327
+ criteria.send(method) do |c|
328
+ c.genres = [ "electro" ]
329
+ end
330
+ end
331
+
332
+ it "returns the new document" do
333
+ expect(band).to be_new_record
334
+ end
335
+
336
+ it "sets the criteria attributes" do
337
+ expect(band.name).to eq("Depeche Mode")
338
+ end
339
+
340
+ it "sets the attributes passed to build" do
341
+ expect(band.genres).to eq([ "electro" ])
342
+ end
343
+ end
344
+ end
345
+ end
346
+ end
347
+
348
+ describe "#cache" do
349
+
350
+ let!(:person) do
351
+ Person.create
352
+ end
353
+
354
+ context "when no eager loading is involved" do
355
+
356
+ let(:criteria) do
357
+ Person.all.cache
358
+ end
359
+
360
+ before do
361
+ criteria.each {}
362
+ end
363
+
364
+ it "does not hit the database after first iteration" do
365
+ criteria.context.query.should_receive(:each).never
366
+ criteria.each do |doc|
367
+ expect(doc).to eq(person)
368
+ end
369
+ end
370
+ end
371
+
372
+ context "when the criteria is eager loading" do
373
+
374
+ let(:criteria) do
375
+ Person.includes(:posts).cache
376
+ end
377
+
378
+ before do
379
+ criteria.each {}
380
+ end
381
+
382
+ it "does not hit the database after first iteration" do
383
+ criteria.context.query.should_receive(:each).never
384
+ criteria.each do |doc|
385
+ expect(doc).to eq(person)
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ [ :clone, :dup ].each do |method|
392
+
393
+ describe "\##{method}" do
394
+
395
+ let(:band) do
396
+ Band.new
397
+ end
398
+
399
+ let(:criteria) do
400
+ Band.where(name: "Depeche Mode").asc(:name).includes(:records)
401
+ end
402
+
403
+ before do
404
+ criteria.documents = [ band ]
405
+ criteria.context
406
+ end
407
+
408
+ let(:clone) do
409
+ criteria.send(method)
410
+ end
411
+
412
+ it "contains an equal selector" do
413
+ expect(clone.selector).to eq({ "name" => "Depeche Mode" })
414
+ end
415
+
416
+ it "clones the selector" do
417
+ expect(clone.selector).to_not equal(criteria.selector)
418
+ end
419
+
420
+ it "contains equal options" do
421
+ expect(clone.options).to eq({ sort: { "name" => 1 }})
422
+ end
423
+
424
+ it "clones the options" do
425
+ expect(clone.options).to_not equal(criteria.options)
426
+ end
427
+
428
+ it "contains equal inclusions" do
429
+ expect(clone.inclusions).to eq([ Band.relations["records"] ])
430
+ end
431
+
432
+ it "clones the inclusions" do
433
+ expect(clone.inclusions).to_not equal(criteria.inclusions)
434
+ end
435
+
436
+ it "contains equal documents" do
437
+ expect(clone.documents).to eq([ band ])
438
+ end
439
+
440
+ it "clones the documents" do
441
+ expect(clone.documents).to_not equal(criteria.documents)
442
+ end
443
+
444
+ it "contains equal scoping options" do
445
+ expect(clone.scoping_options).to eq([ nil, nil ])
446
+ end
447
+
448
+ it "clones the scoping options" do
449
+ expect(clone.scoping_options).to_not equal(criteria.scoping_options)
450
+ end
451
+
452
+ it "sets the context to nil" do
453
+ expect(clone.instance_variable_get(:@context)).to be_nil
454
+ end
455
+ end
456
+ end
457
+
458
+ describe "#cache" do
459
+
460
+ let(:criteria) do
461
+ Band.where(name: "Depeche Mode")
462
+ end
463
+
464
+ it "sets the cache option to true" do
465
+ expect(criteria.cache).to be_cached
466
+ end
467
+ end
468
+
469
+ describe "#context" do
470
+
471
+ context "when the model is embedded" do
472
+
473
+ let(:criteria) do
474
+ described_class.new(Record) do |criteria|
475
+ criteria.embedded = true
476
+ end
477
+ end
478
+
479
+ it "returns the embedded context" do
480
+ expect(criteria.context).to be_a(Mongoid::Contextual::Memory)
481
+ end
482
+ end
483
+
484
+ context "when the model is not embedded" do
485
+
486
+ let(:criteria) do
487
+ described_class.new(Band)
488
+ end
489
+
490
+ it "returns the mongo context" do
491
+ expect(criteria.context).to be_a(Mongoid::Contextual::Mongo)
492
+ end
493
+ end
494
+ end
495
+
496
+ describe "#delete" do
497
+
498
+ let(:depeche) do
499
+ Band.create(name: "Depeche Mode")
500
+ end
501
+
502
+ let(:tool) do
503
+ Band.create(name: "Tool")
504
+ end
505
+
506
+ context "when no selector is provided" do
507
+
508
+ before do
509
+ Band.all.delete
510
+ end
511
+
512
+ it "deletes all the documents from the database" do
513
+ expect(Band.count).to eq(0)
514
+ end
515
+ end
516
+ end
517
+
518
+ describe "#documents" do
519
+
520
+ let(:band) do
521
+ Band.new
522
+ end
523
+
524
+ let(:criteria) do
525
+ described_class.new(Band) do |criteria|
526
+ criteria.documents = [ band ]
527
+ end
528
+ end
529
+
530
+ it "returns the documents" do
531
+ expect(criteria.documents).to eq([ band ])
532
+ end
533
+ end
534
+
535
+ describe "#documents=" do
536
+
537
+ let(:band) do
538
+ Band.new
539
+ end
540
+
541
+ let(:criteria) do
542
+ described_class.new(Band)
543
+ end
544
+
545
+ before do
546
+ criteria.documents = [ band ]
547
+ end
548
+
549
+ it "sets the documents" do
550
+ expect(criteria.documents).to eq([ band ])
551
+ end
552
+ end
553
+
554
+ describe "#each" do
555
+
556
+ let!(:band) do
557
+ Band.create(name: "Depeche Mode")
558
+ end
559
+
560
+ context "when provided a block" do
561
+
562
+ let(:criteria) do
563
+ Band.where(name: "Depeche Mode")
564
+ end
565
+
566
+ it "iterates over the matching documents" do
567
+ criteria.each do |doc|
568
+ expect(doc).to eq(band)
569
+ end
570
+ end
571
+ end
572
+ end
573
+
574
+ describe "#elem_match" do
575
+
576
+ let!(:match) do
577
+ Band.create(name: "Depeche Mode").tap do |band|
578
+ band.records.create(name: "101")
579
+ end
580
+ end
581
+
582
+ let!(:non_match) do
583
+ Band.create(genres: [ "house" ])
584
+ end
585
+
586
+ let(:criteria) do
587
+ Band.elem_match(records: { name: "101" })
588
+ end
589
+
590
+ it "returns the matching documents" do
591
+ expect(criteria).to eq([ match ])
592
+ end
593
+ end
594
+
595
+ describe "#embedded?" do
596
+
597
+ let(:person) do
598
+ Person.new
599
+ end
600
+
601
+ context "when the criteria is embedded" do
602
+
603
+ let(:criteria) do
604
+ person.addresses.where(street: "hobrecht")
605
+ end
606
+
607
+ it "returns true" do
608
+ expect(criteria).to be_embedded
609
+ end
610
+ end
611
+
612
+ context "when the criteria is not embedded" do
613
+
614
+ let(:criteria) do
615
+ Person.where(active: true)
616
+ end
617
+
618
+ it "returns false" do
619
+ expect(criteria).to_not be_embedded
620
+ end
621
+ end
622
+ end
623
+
624
+ describe "#empty?" do
625
+
626
+ context "when matching documents exist" do
627
+
628
+ let!(:match) do
629
+ Band.create(name: "Depeche Mode")
630
+ end
631
+
632
+ let(:criteria) do
633
+ Band.where(name: "Depeche Mode")
634
+ end
635
+
636
+ it "returns false" do
637
+ expect(criteria).to_not be_empty
638
+ end
639
+ end
640
+
641
+ context "when no matching documents exist" do
642
+
643
+ let!(:nonmatch) do
644
+ Band.create(name: "New Order")
645
+ end
646
+
647
+ let(:criteria) do
648
+ Band.where(name: "Depeche Mode")
649
+ end
650
+
651
+ it "returns true" do
652
+ expect(criteria).to be_empty
653
+ end
654
+ end
655
+ end
656
+
657
+ describe "#exists" do
658
+
659
+ let!(:match) do
660
+ Band.create(name: "Depeche Mode")
661
+ end
662
+
663
+ let!(:non_match) do
664
+ Band.create
665
+ end
666
+
667
+ let(:criteria) do
668
+ Band.exists(name: true)
669
+ end
670
+
671
+ it "returns the matching documents" do
672
+ expect(criteria).to eq([ match ])
673
+ end
674
+ end
675
+
676
+ describe "#exists?" do
677
+
678
+ context "when matching documents exist" do
679
+
680
+ let!(:match) do
681
+ Band.create(name: "Depeche Mode")
682
+ end
683
+
684
+ let(:criteria) do
685
+ Band.where(name: "Depeche Mode")
686
+ end
687
+
688
+ it "returns true" do
689
+ expect(criteria.exists?).to be_true
690
+ end
691
+ end
692
+
693
+ context "when no matching documents exist" do
694
+
695
+ let(:criteria) do
696
+ Band.where(name: "Depeche Mode")
697
+ end
698
+
699
+ it "returns false" do
700
+ expect(criteria.exists?).to be_false
701
+ end
702
+ end
703
+ end
704
+
705
+ describe "#explain" do
706
+
707
+ let(:criteria) do
708
+ Band.where(name: "Depeche Mode")
709
+ end
710
+
711
+ it "returns the criteria explain path" do
712
+ expect(criteria.explain["cursor"]).to eq("BasicCursor")
713
+ end
714
+ end
715
+
716
+ describe "#extract_id" do
717
+
718
+ let(:id) do
719
+ Moped::BSON::ObjectId.new
720
+ end
721
+
722
+ context "when an id exists" do
723
+
724
+ let(:criteria) do
725
+ described_class.new(Band) do |criteria|
726
+ criteria.selector[:id] = id
727
+ end
728
+ end
729
+
730
+ it "returns the id" do
731
+ expect(criteria.extract_id).to eq(id)
732
+ end
733
+ end
734
+
735
+ context "when an _id exists" do
736
+
737
+ let(:criteria) do
738
+ described_class.new(Band) do |criteria|
739
+ criteria.selector[:_id] = id
740
+ end
741
+ end
742
+
743
+ it "returns the _id" do
744
+ expect(criteria.extract_id).to eq(id)
745
+ end
746
+ end
747
+ end
748
+
749
+ describe "#field_list" do
750
+
751
+ let(:criteria) do
752
+ Band.only(:name)
753
+ end
754
+
755
+ it "returns the fields minus type" do
756
+ expect(criteria.field_list).to eq([ "name" ])
757
+ end
758
+ end
759
+
760
+ describe "#find_and_modify" do
761
+
762
+ let!(:depeche) do
763
+ Band.create(name: "Depeche Mode")
764
+ end
765
+
766
+ let!(:tool) do
767
+ Band.create(name: "Tool")
768
+ end
769
+
770
+ context "when the selector matches" do
771
+
772
+ context "when the identity map is enabled" do
773
+
774
+ before(:all) do
775
+ Mongoid.identity_map_enabled = true
776
+ end
777
+
778
+ after(:all) do
779
+ Mongoid.identity_map_enabled = false
780
+ end
781
+
782
+ context "when returning the updated document" do
783
+
784
+ let(:criteria) do
785
+ Band.where(name: "Depeche Mode")
786
+ end
787
+
788
+ let(:result) do
789
+ criteria.find_and_modify({ "$inc" => { likes: 1 }}, new: true)
790
+ end
791
+
792
+ it "returns the first matching document" do
793
+ expect(result).to eq(depeche)
794
+ end
795
+
796
+ it "updates the document in the identity map" do
797
+ expect(Mongoid::IdentityMap.get(Band, result.id).likes).to eq(1)
798
+ end
799
+ end
800
+
801
+ context "when not returning the updated document" do
802
+
803
+ let(:criteria) do
804
+ Band.where(name: "Depeche Mode")
805
+ end
806
+
807
+ let!(:result) do
808
+ criteria.find_and_modify("$inc" => { likes: 1 })
809
+ end
810
+
811
+ before do
812
+ depeche.reload
813
+ end
814
+
815
+ it "returns the first matching document" do
816
+ expect(result).to eq(depeche)
817
+ end
818
+
819
+ it "updates the document in the identity map" do
820
+ expect(Mongoid::IdentityMap.get(Band, depeche.id).likes).to eq(1)
821
+ end
822
+ end
823
+ end
824
+
825
+ context "when not providing options" do
826
+
827
+ let(:criteria) do
828
+ Band.where(name: "Depeche Mode")
829
+ end
830
+
831
+ let!(:result) do
832
+ criteria.find_and_modify("$inc" => { likes: 1 })
833
+ end
834
+
835
+ it "returns the first matching document" do
836
+ expect(result).to eq(depeche)
837
+ end
838
+
839
+ it "updates the document in the database" do
840
+ expect(depeche.reload.likes).to eq(1)
841
+ end
842
+ end
843
+
844
+ context "when sorting" do
845
+
846
+ let(:criteria) do
847
+ Band.desc(:name)
848
+ end
849
+
850
+ let!(:result) do
851
+ criteria.find_and_modify("$inc" => { likes: 1 })
852
+ end
853
+
854
+ it "returns the first matching document" do
855
+ expect(result).to eq(tool)
856
+ end
857
+
858
+ it "updates the document in the database" do
859
+ expect(tool.reload.likes).to eq(1)
860
+ end
861
+ end
862
+
863
+ context "when limiting fields" do
864
+
865
+ let(:criteria) do
866
+ Band.only(:_id)
867
+ end
868
+
869
+ let!(:result) do
870
+ criteria.find_and_modify("$inc" => { likes: 1 })
871
+ end
872
+
873
+ it "returns the first matching document" do
874
+ expect(result).to eq(depeche)
875
+ end
876
+
877
+ it "limits the returned fields" do
878
+ expect(result.name).to be_nil
879
+ end
880
+
881
+ it "updates the document in the database" do
882
+ expect(depeche.reload.likes).to eq(1)
883
+ end
884
+ end
885
+
886
+ context "when returning new" do
887
+
888
+ let(:criteria) do
889
+ Band.where(name: "Depeche Mode")
890
+ end
891
+
892
+ let!(:result) do
893
+ criteria.find_and_modify({ "$inc" => { likes: 1 }}, new: true)
894
+ end
895
+
896
+ it "returns the first matching document" do
897
+ expect(result).to eq(depeche)
898
+ end
899
+
900
+ it "returns the updated document" do
901
+ expect(result.likes).to eq(1)
902
+ end
903
+ end
904
+
905
+ context "when removing" do
906
+
907
+ let(:criteria) do
908
+ Band.where(name: "Depeche Mode")
909
+ end
910
+
911
+ let!(:result) do
912
+ criteria.find_and_modify({}, remove: true)
913
+ end
914
+
915
+ it "returns the first matching document" do
916
+ expect(result).to eq(depeche)
917
+ end
918
+
919
+ it "deletes the document from the database" do
920
+ expect {
921
+ depeche.reload
922
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
923
+ end
924
+ end
925
+ end
926
+
927
+ context "when the selector does not match" do
928
+
929
+ let(:criteria) do
930
+ Band.where(name: "Placebo")
931
+ end
932
+
933
+ let(:result) do
934
+ criteria.find_and_modify("$inc" => { likes: 1 })
935
+ end
936
+
937
+ it "returns nil" do
938
+ expect(result).to be_nil
939
+ end
940
+ end
941
+ end
942
+
943
+ describe "#freeze" do
944
+
945
+ let(:criteria) do
946
+ Band.all
947
+ end
948
+
949
+ before do
950
+ criteria.freeze
951
+ end
952
+
953
+ it "freezes the criteria" do
954
+ expect(criteria).to be_frozen
955
+ end
956
+
957
+ it "initializes inclusions" do
958
+ expect(criteria.inclusions).to be_empty
959
+ end
960
+
961
+ it "initializes the context" do
962
+ expect(criteria.context).to_not be_nil
963
+ end
964
+ end
965
+
966
+ describe "#geo_near" do
967
+
968
+ before do
969
+ Bar.create_indexes
970
+ end
971
+
972
+ let!(:match) do
973
+ Bar.create(location: [ 52.30, 13.25 ])
974
+ end
975
+
976
+ let(:criteria) do
977
+ Bar.geo_near([ 52, 13 ]).max_distance(10).spherical
978
+ end
979
+
980
+ it "returns the matching documents" do
981
+ expect(criteria).to eq([ match ])
982
+ end
983
+ end
984
+
985
+ describe "#gt" do
986
+
987
+ let!(:match) do
988
+ Band.create(member_count: 5)
989
+ end
990
+
991
+ let!(:non_match) do
992
+ Band.create(member_count: 1)
993
+ end
994
+
995
+ let(:criteria) do
996
+ Band.gt(member_count: 4)
997
+ end
998
+
999
+ it "returns the matching documents" do
1000
+ expect(criteria).to eq([ match ])
1001
+ end
1002
+ end
1003
+
1004
+ describe "#gte" do
1005
+
1006
+ let!(:match) do
1007
+ Band.create(member_count: 5)
1008
+ end
1009
+
1010
+ let!(:non_match) do
1011
+ Band.create(member_count: 1)
1012
+ end
1013
+
1014
+ let(:criteria) do
1015
+ Band.gte(member_count: 5)
1016
+ end
1017
+
1018
+ it "returns the matching documents" do
1019
+ expect(criteria).to eq([ match ])
1020
+ end
1021
+ end
1022
+
1023
+ [ :in, :any_in ].each do |method|
1024
+
1025
+ describe "\##{method}" do
1026
+
1027
+ context "when querying on a normal field" do
1028
+
1029
+ let!(:match) do
1030
+ Band.create(genres: [ "electro", "dub" ])
1031
+ end
1032
+
1033
+ let!(:non_match) do
1034
+ Band.create(genres: [ "house" ])
1035
+ end
1036
+
1037
+ let(:criteria) do
1038
+ Band.send(method, genres: [ "dub" ])
1039
+ end
1040
+
1041
+ it "returns the matching documents" do
1042
+ expect(criteria).to eq([ match ])
1043
+ end
1044
+ end
1045
+
1046
+ context "when querying on a foreign key" do
1047
+
1048
+ let(:id) do
1049
+ Moped::BSON::ObjectId.new
1050
+ end
1051
+
1052
+ let!(:match_one) do
1053
+ Person.create(preference_ids: [ id ])
1054
+ end
1055
+
1056
+ context "when providing valid ids" do
1057
+
1058
+ let(:criteria) do
1059
+ Person.send(method, preference_ids: [ id ])
1060
+ end
1061
+
1062
+ it "returns the matching documents" do
1063
+ expect(criteria).to eq([ match_one ])
1064
+ end
1065
+ end
1066
+
1067
+ context "when providing empty strings" do
1068
+
1069
+ let(:criteria) do
1070
+ Person.send(method, preference_ids: [ id, "" ])
1071
+ end
1072
+
1073
+ it "returns the matching documents" do
1074
+ expect(criteria).to eq([ match_one ])
1075
+ end
1076
+ end
1077
+
1078
+ context "when providing nils" do
1079
+
1080
+ context "when the relation is a many to many" do
1081
+
1082
+ let(:criteria) do
1083
+ Person.send(method, preference_ids: [ id, nil ])
1084
+ end
1085
+
1086
+ it "returns the matching documents" do
1087
+ expect(criteria).to eq([ match_one ])
1088
+ end
1089
+ end
1090
+
1091
+ context "when the relation is a one to one" do
1092
+
1093
+ let!(:game) do
1094
+ Game.create
1095
+ end
1096
+
1097
+ let(:criteria) do
1098
+ Game.send(method, person_id: [ nil ])
1099
+ end
1100
+
1101
+ it "returns the matching documents" do
1102
+ expect(criteria).to eq([ game ])
1103
+ end
1104
+ end
1105
+ end
1106
+ end
1107
+ end
1108
+ end
1109
+
1110
+ describe "#initialize" do
1111
+
1112
+ let(:criteria) do
1113
+ described_class.new(Band)
1114
+ end
1115
+
1116
+ it "sets the class" do
1117
+ expect(criteria.klass).to eq(Band)
1118
+ end
1119
+
1120
+ it "sets the aliased fields" do
1121
+ expect(criteria.aliased_fields).to eq(Band.aliased_fields)
1122
+ end
1123
+
1124
+ it "sets the serializers" do
1125
+ expect(criteria.serializers).to eq(Band.fields)
1126
+ end
1127
+ end
1128
+
1129
+ describe "#includes" do
1130
+
1131
+ before do
1132
+ Mongoid.identity_map_enabled = true
1133
+ end
1134
+
1135
+ after do
1136
+ Mongoid.identity_map_enabled = false
1137
+ end
1138
+
1139
+ let!(:person) do
1140
+ Person.create
1141
+ end
1142
+
1143
+ context "when providing a name that is not a relation" do
1144
+
1145
+ it "raises an error" do
1146
+ expect {
1147
+ Person.includes(:members)
1148
+ }.to raise_error(Mongoid::Errors::InvalidIncludes)
1149
+ end
1150
+ end
1151
+
1152
+ context "when providing a hash" do
1153
+
1154
+ it "raises an error" do
1155
+ expect {
1156
+ Person.includes(preferences: :members)
1157
+ }.to raise_error(Mongoid::Errors::InvalidIncludes)
1158
+ end
1159
+ end
1160
+
1161
+ context "when the models are inherited" do
1162
+
1163
+ before(:all) do
1164
+ class A
1165
+ include Mongoid::Document
1166
+ end
1167
+
1168
+ class B < A
1169
+ belongs_to :c
1170
+ end
1171
+
1172
+ class C
1173
+ include Mongoid::Document
1174
+ has_one :b
1175
+ end
1176
+ end
1177
+
1178
+ after(:all) do
1179
+ Object.send(:remove_const, :A)
1180
+ Object.send(:remove_const, :B)
1181
+ Object.send(:remove_const, :C)
1182
+ end
1183
+
1184
+ context "when the includes is on the subclass" do
1185
+
1186
+ let!(:c_one) do
1187
+ C.create
1188
+ end
1189
+
1190
+ let!(:c_two) do
1191
+ C.create
1192
+ end
1193
+
1194
+ let!(:b) do
1195
+ B.create(c: c_two)
1196
+ end
1197
+
1198
+ before do
1199
+ Mongoid::IdentityMap.clear
1200
+ end
1201
+
1202
+ let!(:results) do
1203
+ C.includes(:b).entries.detect do |c|
1204
+ c.id == c_two.id
1205
+ end
1206
+ end
1207
+
1208
+ let(:from_map) do
1209
+ Mongoid::IdentityMap[B.collection_name][b.id]
1210
+ end
1211
+
1212
+ it "returns the correct documents" do
1213
+ expect(results).to eq(c_two)
1214
+ end
1215
+
1216
+ it "inserts the first document into the identity map" do
1217
+ expect(from_map).to eq(b)
1218
+ end
1219
+
1220
+ it "retrieves the document from the identity map" do
1221
+ expect(results.b).to equal(from_map)
1222
+ end
1223
+ end
1224
+ end
1225
+
1226
+ context "when the models are inherited from another one model" do
1227
+
1228
+ context "when the relation is a has_one" do
1229
+
1230
+ before(:all) do
1231
+ class A
1232
+ include Mongoid::Document
1233
+ end
1234
+
1235
+ class B < A
1236
+ belongs_to :d
1237
+ end
1238
+
1239
+ class C < A
1240
+ belongs_to :d
1241
+ end
1242
+
1243
+ class D
1244
+ include Mongoid::Document
1245
+ has_one :b
1246
+ has_one :c
1247
+ end
1248
+ end
1249
+
1250
+ after(:all) do
1251
+ Object.send(:remove_const, :A)
1252
+ Object.send(:remove_const, :B)
1253
+ Object.send(:remove_const, :C)
1254
+ Object.send(:remove_const, :D)
1255
+ end
1256
+
1257
+ context "when the includes is on the several relations" do
1258
+
1259
+ let!(:d_one) do
1260
+ D.create
1261
+ end
1262
+
1263
+ let!(:d_two) do
1264
+ D.create
1265
+ end
1266
+
1267
+ let!(:b) do
1268
+ B.create(d: d_two)
1269
+ end
1270
+
1271
+ let!(:c) do
1272
+ C.create(d: d_two)
1273
+ end
1274
+
1275
+ before do
1276
+ Mongoid::IdentityMap.clear
1277
+ end
1278
+
1279
+ let!(:results) do
1280
+ D.includes(:b, :c).entries.detect do |d|
1281
+ d.id == d_two.id
1282
+ end
1283
+ end
1284
+
1285
+ let(:from_map_b) do
1286
+ Mongoid::IdentityMap[B.collection_name][b.id]
1287
+ end
1288
+
1289
+ let(:from_map_c) do
1290
+ Mongoid::IdentityMap[C.collection_name][c.id]
1291
+ end
1292
+
1293
+ it "returns the correct documents" do
1294
+ expect(results).to eq(d_two)
1295
+ end
1296
+
1297
+ it "inserts the b document into the identity map" do
1298
+ expect(from_map_b).to eq(b)
1299
+ end
1300
+
1301
+ it "inserts the c document into the identity map" do
1302
+ expect(from_map_c).to eq(c)
1303
+ end
1304
+
1305
+ it "retrieves the b document from the identity map" do
1306
+ expect(results.b).to equal(from_map_b)
1307
+ end
1308
+
1309
+ it "retrieves the c document from the identity map" do
1310
+ expect(results.c).to equal(from_map_c)
1311
+ end
1312
+ end
1313
+ end
1314
+
1315
+ context "when the relation is a has_many" do
1316
+
1317
+ before(:all) do
1318
+ class A
1319
+ include Mongoid::Document
1320
+ end
1321
+
1322
+ class B < A
1323
+ belongs_to :d
1324
+ end
1325
+
1326
+ class C < A
1327
+ belongs_to :d
1328
+ end
1329
+
1330
+ class D
1331
+ include Mongoid::Document
1332
+ has_many :b
1333
+ has_many :c
1334
+ end
1335
+ end
1336
+
1337
+ after(:all) do
1338
+ Object.send(:remove_const, :A)
1339
+ Object.send(:remove_const, :B)
1340
+ Object.send(:remove_const, :C)
1341
+ Object.send(:remove_const, :D)
1342
+ end
1343
+
1344
+ context "when the includes is on the several relations" do
1345
+
1346
+ let!(:d_one) do
1347
+ D.create
1348
+ end
1349
+
1350
+ let!(:d_two) do
1351
+ D.create
1352
+ end
1353
+
1354
+ let!(:bs) do
1355
+ 2.times.map { B.create(d: d_two) }
1356
+ end
1357
+
1358
+ let!(:cs) do
1359
+ 2.times.map { C.create(d: d_two) }
1360
+ end
1361
+
1362
+ before do
1363
+ Mongoid::IdentityMap.clear
1364
+ end
1365
+
1366
+ let!(:results) do
1367
+ D.includes(:b, :c).entries.detect do |d|
1368
+ d.id == d_two.id
1369
+ end
1370
+ end
1371
+
1372
+ let(:from_map_bs) do
1373
+ bs.map { |b| Mongoid::IdentityMap[B.collection_name][b.id] }
1374
+ end
1375
+
1376
+ let(:from_map_cs) do
1377
+ cs.map { |c| Mongoid::IdentityMap[C.collection_name][c.id] }
1378
+ end
1379
+
1380
+ it "returns the correct documents" do
1381
+ expect(results).to eq(d_two)
1382
+ end
1383
+
1384
+ it "inserts the b documents into the identity map" do
1385
+ expect(from_map_bs).to eq(bs)
1386
+ end
1387
+
1388
+ it "inserts the c documents into the identity map" do
1389
+ expect(from_map_cs).to eq(cs)
1390
+ end
1391
+
1392
+ it "retrieves the b documents from the identity map" do
1393
+ expect(results.b).to match_array(from_map_bs)
1394
+ end
1395
+
1396
+ it "retrieves the c documents from the identity map" do
1397
+ expect(results.c).to match_array(from_map_cs)
1398
+ end
1399
+ end
1400
+ end
1401
+ end
1402
+
1403
+ context "when including the same metadata multiple times" do
1404
+
1405
+ let(:criteria) do
1406
+ Person.all.includes(:posts, :posts).includes(:posts)
1407
+ end
1408
+
1409
+ let(:metadata) do
1410
+ Person.reflect_on_association(:posts)
1411
+ end
1412
+
1413
+ it "does not duplicate the metadata in the inclusions" do
1414
+ expect(criteria.inclusions).to eq([ metadata ])
1415
+ end
1416
+ end
1417
+
1418
+ context "when mapping the results more than once" do
1419
+
1420
+ before do
1421
+ Mongoid::IdentityMap.clear
1422
+ end
1423
+
1424
+ let!(:post) do
1425
+ person.posts.create(title: "one")
1426
+ end
1427
+
1428
+ let(:criteria) do
1429
+ Post.includes(:person)
1430
+ end
1431
+
1432
+ let!(:results) do
1433
+ criteria.map { |doc| doc }
1434
+ criteria.map { |doc| doc }
1435
+ end
1436
+
1437
+ it "returns the proper results" do
1438
+ expect(results.first.title).to eq("one")
1439
+ end
1440
+ end
1441
+
1442
+ context "when including a belongs to relation" do
1443
+
1444
+ context "when the criteria is from an embedded relation" do
1445
+
1446
+ let(:peep) do
1447
+ Person.create
1448
+ end
1449
+
1450
+ let!(:address_one) do
1451
+ peep.addresses.create(street: "rosenthaler")
1452
+ end
1453
+
1454
+ let!(:address_two) do
1455
+ peep.addresses.create(street: "weinmeister")
1456
+ end
1457
+
1458
+ let!(:depeche) do
1459
+ Band.create!(name: "Depeche Mode")
1460
+ end
1461
+
1462
+ let!(:tool) do
1463
+ Band.create!(name: "Tool")
1464
+ end
1465
+
1466
+ before do
1467
+ address_one.band = depeche
1468
+ address_two.band = tool
1469
+ address_one.save
1470
+ address_two.save
1471
+ end
1472
+
1473
+ context "when calling first" do
1474
+
1475
+ before do
1476
+ Mongoid::IdentityMap.clear
1477
+ end
1478
+
1479
+ let(:criteria) do
1480
+ peep.reload.addresses.includes(:band)
1481
+ end
1482
+
1483
+ let(:context) do
1484
+ criteria.context
1485
+ end
1486
+
1487
+ before do
1488
+ context.should_receive(:eager_load_one).with(address_one).once.and_call_original
1489
+ end
1490
+
1491
+ let!(:document) do
1492
+ criteria.first
1493
+ end
1494
+
1495
+ let(:eager_loaded) do
1496
+ Mongoid::IdentityMap[Band.collection_name]
1497
+ end
1498
+
1499
+ it "eager loads the first document" do
1500
+ expect(eager_loaded[depeche.id]).to eq(depeche)
1501
+ end
1502
+
1503
+ it "does not eager load the last document" do
1504
+ expect(eager_loaded[tool.id]).to be_nil
1505
+ end
1506
+
1507
+ it "returns the document" do
1508
+ expect(document).to eq(address_one)
1509
+ end
1510
+ end
1511
+
1512
+ context "when calling last" do
1513
+
1514
+ before do
1515
+ Mongoid::IdentityMap.clear
1516
+ end
1517
+
1518
+ let(:criteria) do
1519
+ peep.reload.addresses.includes(:band)
1520
+ end
1521
+
1522
+ let(:context) do
1523
+ criteria.context
1524
+ end
1525
+
1526
+ before do
1527
+ context.should_receive(:eager_load_one).with(address_two).once.and_call_original
1528
+ end
1529
+
1530
+ let!(:document) do
1531
+ criteria.last
1532
+ end
1533
+
1534
+ let(:eager_loaded) do
1535
+ Mongoid::IdentityMap[Band.collection_name]
1536
+ end
1537
+
1538
+ it "does not eager load the first document" do
1539
+ expect(eager_loaded[depeche.id]).to be_nil
1540
+ end
1541
+
1542
+ it "eager loads the last document" do
1543
+ expect(eager_loaded[tool.id]).to eq(tool)
1544
+ end
1545
+
1546
+ it "returns the document" do
1547
+ expect(document).to eq(address_two)
1548
+ end
1549
+ end
1550
+
1551
+ context "when iterating all documents" do
1552
+
1553
+ before do
1554
+ Mongoid::IdentityMap.clear
1555
+ end
1556
+
1557
+ let(:criteria) do
1558
+ peep.reload.addresses.includes(:band)
1559
+ end
1560
+
1561
+ let(:context) do
1562
+ criteria.context
1563
+ end
1564
+
1565
+ before do
1566
+ context.
1567
+ should_receive(:eager_load).
1568
+ with([ address_one, address_two ]).
1569
+ once.
1570
+ and_call_original
1571
+ end
1572
+
1573
+ let!(:documents) do
1574
+ criteria.to_a
1575
+ end
1576
+
1577
+ let(:eager_loaded) do
1578
+ Mongoid::IdentityMap[Band.collection_name]
1579
+ end
1580
+
1581
+ it "eager loads the first document" do
1582
+ expect(eager_loaded[depeche.id]).to eq(depeche)
1583
+ end
1584
+
1585
+ it "eager loads the last document" do
1586
+ expect(eager_loaded[tool.id]).to eq(tool)
1587
+ end
1588
+
1589
+ it "returns the documents" do
1590
+ expect(documents).to eq([ address_one, address_two ])
1591
+ end
1592
+ end
1593
+ end
1594
+
1595
+ context "when the criteria is from the root" do
1596
+
1597
+ let!(:person_two) do
1598
+ Person.create
1599
+ end
1600
+
1601
+ let!(:post_one) do
1602
+ person.posts.create(title: "one")
1603
+ end
1604
+
1605
+ let!(:post_two) do
1606
+ person_two.posts.create(title: "two")
1607
+ end
1608
+
1609
+ before do
1610
+ Mongoid::IdentityMap.clear
1611
+ end
1612
+
1613
+ context "when calling first" do
1614
+
1615
+ let!(:criteria) do
1616
+ Post.includes(:person)
1617
+ end
1618
+
1619
+ let!(:context) do
1620
+ criteria.context
1621
+ end
1622
+
1623
+ before do
1624
+ context.should_receive(:eager_load_one).with(post_one).once.and_call_original
1625
+ end
1626
+
1627
+ let!(:document) do
1628
+ criteria.first
1629
+ end
1630
+
1631
+ it "eager loads for the first document" do
1632
+ expect(Mongoid::IdentityMap[Person.collection_name][person.id]).to eq(person)
1633
+ end
1634
+
1635
+ it "does not eager loads for the last document" do
1636
+ expect(Mongoid::IdentityMap[Person.collection_name][person_two.id]).to be_nil
1637
+ end
1638
+
1639
+ it "returns the first document" do
1640
+ expect(document).to eq(post_one)
1641
+ end
1642
+ end
1643
+
1644
+ context "when calling last" do
1645
+
1646
+ let!(:criteria) do
1647
+ Post.includes(:person)
1648
+ end
1649
+
1650
+ let!(:context) do
1651
+ criteria.context
1652
+ end
1653
+
1654
+ before do
1655
+ context.should_receive(:eager_load_one).with(post_two).once.and_call_original
1656
+ end
1657
+
1658
+ let!(:document) do
1659
+ criteria.last
1660
+ end
1661
+
1662
+ it "eager loads for the first document" do
1663
+ expect(Mongoid::IdentityMap[Person.collection_name][person_two.id]).to eq(person_two)
1664
+ end
1665
+
1666
+ it "does not eager loads for the last document" do
1667
+ expect(Mongoid::IdentityMap[Person.collection_name][person.id]).to be_nil
1668
+ end
1669
+
1670
+ it "returns the last document" do
1671
+ expect(document).to eq(post_two)
1672
+ end
1673
+ end
1674
+ end
1675
+ end
1676
+
1677
+ context "when providing inclusions to the default scope" do
1678
+
1679
+ before do
1680
+ Person.default_scope(Person.includes(:posts))
1681
+ end
1682
+
1683
+ after do
1684
+ Person.default_scoping = nil
1685
+ end
1686
+
1687
+ let!(:post_one) do
1688
+ person.posts.create(title: "one")
1689
+ end
1690
+
1691
+ let!(:post_two) do
1692
+ person.posts.create(title: "two")
1693
+ end
1694
+
1695
+ context "when the criteria has no options" do
1696
+
1697
+ before do
1698
+ Mongoid::IdentityMap.clear
1699
+ end
1700
+
1701
+ let!(:criteria) do
1702
+ Person.all
1703
+ end
1704
+
1705
+ let!(:context) do
1706
+ criteria.context
1707
+ end
1708
+
1709
+ before do
1710
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
1711
+ end
1712
+
1713
+ let!(:documents) do
1714
+ criteria.entries
1715
+ end
1716
+
1717
+ it "returns the correct documents" do
1718
+ expect(documents).to eq([ person ])
1719
+ end
1720
+
1721
+ it "inserts the first document into the identity map" do
1722
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
1723
+ end
1724
+
1725
+ it "inserts the second document into the identity map" do
1726
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
1727
+ end
1728
+
1729
+ context "when executing the query twice" do
1730
+
1731
+ let!(:new_criteria) do
1732
+ Person.where(id: person.id)
1733
+ end
1734
+
1735
+ let!(:new_context) do
1736
+ new_criteria.context
1737
+ end
1738
+
1739
+ before do
1740
+ new_context.should_receive(:eager_load_one).with(person).once.and_call_original
1741
+ end
1742
+
1743
+ let!(:from_db) do
1744
+ new_criteria.first
1745
+ end
1746
+
1747
+ let(:mapped) do
1748
+ Mongoid::IdentityMap[Post.collection_name][{"person_id" => person.id}]
1749
+ end
1750
+
1751
+ it "does not duplicate documents in the relation" do
1752
+ expect(person.posts.size).to eq(2)
1753
+ end
1754
+
1755
+ it "does not duplicate documents in the map" do
1756
+ expect(mapped.size).to eq(2)
1757
+ end
1758
+ end
1759
+ end
1760
+
1761
+ context "when calling first on the criteria" do
1762
+
1763
+ before do
1764
+ Mongoid::IdentityMap.clear
1765
+ end
1766
+
1767
+ let(:criteria) do
1768
+ Person.all
1769
+ end
1770
+
1771
+ let!(:context) do
1772
+ criteria.context
1773
+ end
1774
+
1775
+ before do
1776
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
1777
+ end
1778
+
1779
+ let!(:from_db) do
1780
+ criteria.first
1781
+ end
1782
+
1783
+ it "returns the correct documents" do
1784
+ expect(from_db).to eq(person)
1785
+ end
1786
+
1787
+ it "inserts the first document into the identity map" do
1788
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
1789
+ end
1790
+
1791
+ it "inserts the second document into the identity map" do
1792
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
1793
+ end
1794
+ end
1795
+
1796
+ context "when calling last on the criteria" do
1797
+
1798
+ before do
1799
+ Mongoid::IdentityMap.clear
1800
+ end
1801
+
1802
+ let(:criteria) do
1803
+ Person.all
1804
+ end
1805
+
1806
+ let!(:context) do
1807
+ criteria.context
1808
+ end
1809
+
1810
+ before do
1811
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
1812
+ end
1813
+
1814
+ let!(:from_db) do
1815
+ criteria.last
1816
+ end
1817
+
1818
+ it "returns the correct documents" do
1819
+ expect(from_db).to eq(person)
1820
+ end
1821
+
1822
+ it "inserts the first document into the identity map" do
1823
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
1824
+ end
1825
+
1826
+ it "inserts the second document into the identity map" do
1827
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
1828
+ end
1829
+ end
1830
+
1831
+ context "when the criteria has limiting options" do
1832
+
1833
+ let!(:person_two) do
1834
+ Person.create
1835
+ end
1836
+
1837
+ let!(:post_three) do
1838
+ person_two.posts.create(title: "three")
1839
+ end
1840
+
1841
+ before do
1842
+ Mongoid::IdentityMap.clear
1843
+ end
1844
+
1845
+ let!(:criteria) do
1846
+ Person.asc(:_id).limit(1)
1847
+ end
1848
+
1849
+ let(:context) do
1850
+ criteria.context
1851
+ end
1852
+
1853
+ before do
1854
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
1855
+ end
1856
+
1857
+ let!(:documents) do
1858
+ criteria.entries
1859
+ end
1860
+
1861
+ it "returns the correct documents" do
1862
+ expect(criteria).to eq([ person ])
1863
+ end
1864
+
1865
+ it "inserts the first document into the identity map" do
1866
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
1867
+ end
1868
+
1869
+ it "inserts the second document into the identity map" do
1870
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
1871
+ end
1872
+
1873
+ it "does not insert the third post into the identity map" do
1874
+ expect(Mongoid::IdentityMap[Post.collection_name][post_three.id]).to be_nil
1875
+ end
1876
+ end
1877
+ end
1878
+
1879
+ context "when including a has and belongs to many" do
1880
+
1881
+ let!(:preference_one) do
1882
+ person.preferences.create(name: "one")
1883
+ end
1884
+
1885
+ let!(:preference_two) do
1886
+ person.preferences.create(name: "two")
1887
+ end
1888
+
1889
+ context "when the criteria has no options" do
1890
+
1891
+ before do
1892
+ Mongoid::IdentityMap.clear
1893
+ end
1894
+
1895
+ let!(:criteria) do
1896
+ Person.includes(:preferences)
1897
+ end
1898
+
1899
+ let(:context) do
1900
+ criteria.context
1901
+ end
1902
+
1903
+ before do
1904
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
1905
+ end
1906
+
1907
+ let!(:documents) do
1908
+ criteria.entries
1909
+ end
1910
+
1911
+ it "returns the correct documents" do
1912
+ expect(documents).to eq([ person ])
1913
+ end
1914
+
1915
+ let(:preference_map) do
1916
+ Mongoid::IdentityMap[Preference.collection_name]
1917
+ end
1918
+
1919
+ it "inserts the first document into the identity map" do
1920
+ expect(preference_map[preference_one.id]).to eq(preference_one)
1921
+ end
1922
+
1923
+ it "inserts the second document into the identity map" do
1924
+ expect(preference_map[preference_two.id]).to eq(preference_two)
1925
+ end
1926
+ end
1927
+
1928
+ context "when calling first on the criteria" do
1929
+
1930
+ before do
1931
+ Mongoid::IdentityMap.clear
1932
+ end
1933
+
1934
+ let!(:criteria) do
1935
+ Person.includes(:preferences)
1936
+ end
1937
+
1938
+ let(:context) do
1939
+ criteria.context
1940
+ end
1941
+
1942
+ before do
1943
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
1944
+ end
1945
+
1946
+ let!(:from_db) do
1947
+ criteria.first
1948
+ end
1949
+
1950
+ it "returns the correct documents" do
1951
+ expect(from_db).to eq(person)
1952
+ end
1953
+
1954
+ let(:preference_map) do
1955
+ Mongoid::IdentityMap[Preference.collection_name]
1956
+ end
1957
+
1958
+ it "inserts the first document into the identity map" do
1959
+ expect(preference_map[preference_one.id]).to eq(preference_one)
1960
+ end
1961
+
1962
+ it "inserts the second document into the identity map" do
1963
+ expect(preference_map[preference_two.id]).to eq(preference_two)
1964
+ end
1965
+ end
1966
+
1967
+ context "when calling last on the criteria" do
1968
+
1969
+ before do
1970
+ Mongoid::IdentityMap.clear
1971
+ end
1972
+
1973
+ let!(:criteria) do
1974
+ Person.includes(:preferences)
1975
+ end
1976
+
1977
+ let(:context) do
1978
+ criteria.context
1979
+ end
1980
+
1981
+ before do
1982
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
1983
+ end
1984
+
1985
+ let!(:from_db) do
1986
+ criteria.last
1987
+ end
1988
+
1989
+ it "returns the correct documents" do
1990
+ expect(from_db).to eq(person)
1991
+ end
1992
+
1993
+ let(:preference_map) do
1994
+ Mongoid::IdentityMap[Preference.collection_name]
1995
+ end
1996
+
1997
+ it "inserts the first document into the identity map" do
1998
+ expect(preference_map[preference_one.id]).to eq(preference_one)
1999
+ end
2000
+
2001
+ it "inserts the second document into the identity map" do
2002
+ expect(preference_map[preference_two.id]).to eq(preference_two)
2003
+ end
2004
+ end
2005
+
2006
+ context "when the criteria has limiting options" do
2007
+
2008
+ let!(:person_two) do
2009
+ Person.create
2010
+ end
2011
+
2012
+ let!(:preference_three) do
2013
+ person_two.preferences.create(name: "three")
2014
+ end
2015
+
2016
+ before do
2017
+ Mongoid::IdentityMap.clear
2018
+ end
2019
+
2020
+ let!(:criteria) do
2021
+ Person.includes(:preferences).asc(:_id).limit(1)
2022
+ end
2023
+
2024
+ let(:context) do
2025
+ criteria.context
2026
+ end
2027
+
2028
+ before do
2029
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2030
+ end
2031
+
2032
+ let!(:documents) do
2033
+ criteria.entries
2034
+ end
2035
+
2036
+ let(:preference_map) do
2037
+ Mongoid::IdentityMap[Preference.collection_name]
2038
+ end
2039
+
2040
+ it "returns the correct documents" do
2041
+ expect(documents).to eq([ person ])
2042
+ end
2043
+
2044
+ it "inserts the first document into the identity map" do
2045
+ expect(preference_map[preference_one.id]).to eq(preference_one)
2046
+ end
2047
+
2048
+ it "inserts the second document into the identity map" do
2049
+ expect(preference_map[preference_two.id]).to eq(preference_two)
2050
+ end
2051
+
2052
+ it "does not insert the third preference into the identity map" do
2053
+ expect(preference_map[preference_three.id]).to be_nil
2054
+ end
2055
+ end
2056
+ end
2057
+
2058
+ context "when including a has many" do
2059
+
2060
+ let!(:post_one) do
2061
+ person.posts.create(title: "one")
2062
+ end
2063
+
2064
+ let!(:post_two) do
2065
+ person.posts.create(title: "two")
2066
+ end
2067
+
2068
+ context "when the criteria has no options" do
2069
+
2070
+ before do
2071
+ Mongoid::IdentityMap.clear
2072
+ end
2073
+
2074
+ let!(:criteria) do
2075
+ Person.includes(:posts)
2076
+ end
2077
+
2078
+ let(:context) do
2079
+ criteria.context
2080
+ end
2081
+
2082
+ before do
2083
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2084
+ end
2085
+
2086
+ let!(:documents) do
2087
+ criteria.entries
2088
+ end
2089
+
2090
+ it "returns the correct documents" do
2091
+ expect(documents).to eq([ person ])
2092
+ end
2093
+
2094
+ it "inserts the first document into the identity map" do
2095
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
2096
+ end
2097
+
2098
+ it "inserts the second document into the identity map" do
2099
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
2100
+ end
2101
+ end
2102
+
2103
+ context "when calling first on the criteria" do
2104
+
2105
+ before do
2106
+ Mongoid::IdentityMap.clear
2107
+ end
2108
+
2109
+ let!(:criteria) do
2110
+ Person.includes(:posts)
2111
+ end
2112
+
2113
+ let(:context) do
2114
+ criteria.context
2115
+ end
2116
+
2117
+ before do
2118
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
2119
+ end
2120
+
2121
+ let!(:from_db) do
2122
+ criteria.first
2123
+ end
2124
+
2125
+ it "returns the correct documents" do
2126
+ expect(from_db).to eq(person)
2127
+ end
2128
+
2129
+ it "inserts the first document into the identity map" do
2130
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
2131
+ end
2132
+
2133
+ it "inserts the second document into the identity map" do
2134
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
2135
+ end
2136
+
2137
+ context "when subsequently getting all documents" do
2138
+
2139
+ before do
2140
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2141
+ end
2142
+
2143
+ let!(:documents) do
2144
+ criteria.entries
2145
+ end
2146
+
2147
+ it "returns the correct documents" do
2148
+ expect(documents).to eq([ person ])
2149
+ end
2150
+ end
2151
+ end
2152
+
2153
+ context "when calling last on the criteria" do
2154
+
2155
+ before do
2156
+ Mongoid::IdentityMap.clear
2157
+ end
2158
+
2159
+ let!(:criteria) do
2160
+ Person.includes(:posts)
2161
+ end
2162
+
2163
+ let(:context) do
2164
+ criteria.context
2165
+ end
2166
+
2167
+ before do
2168
+ context.should_receive(:eager_load_one).with(person).once.and_call_original
2169
+ end
2170
+
2171
+ let!(:from_db) do
2172
+ criteria.last
2173
+ end
2174
+
2175
+ it "returns the correct documents" do
2176
+ expect(from_db).to eq(person)
2177
+ end
2178
+
2179
+ it "inserts the first document into the identity map" do
2180
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
2181
+ end
2182
+
2183
+ it "inserts the second document into the identity map" do
2184
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
2185
+ end
2186
+
2187
+ context "when subsequently getting all documents" do
2188
+
2189
+ before do
2190
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2191
+ end
2192
+
2193
+ let!(:documents) do
2194
+ criteria.entries
2195
+ end
2196
+
2197
+ it "returns the correct documents" do
2198
+ expect(documents).to eq([ person ])
2199
+ end
2200
+ end
2201
+ end
2202
+
2203
+ context "when the criteria has limiting options" do
2204
+
2205
+ let!(:person_two) do
2206
+ Person.create
2207
+ end
2208
+
2209
+ let!(:post_three) do
2210
+ person_two.posts.create(title: "three")
2211
+ end
2212
+
2213
+ before do
2214
+ Mongoid::IdentityMap.clear
2215
+ end
2216
+
2217
+ let!(:criteria) do
2218
+ Person.includes(:posts).asc(:_id).limit(1)
2219
+ end
2220
+
2221
+ let(:context) do
2222
+ criteria.context
2223
+ end
2224
+
2225
+ before do
2226
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2227
+ end
2228
+
2229
+ let!(:documents) do
2230
+ criteria.entries
2231
+ end
2232
+
2233
+ it "returns the correct documents" do
2234
+ expect(documents).to eq([ person ])
2235
+ end
2236
+
2237
+ it "inserts the first document into the identity map" do
2238
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
2239
+ end
2240
+
2241
+ it "inserts the second document into the identity map" do
2242
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
2243
+ end
2244
+
2245
+ it "does not insert the third post into the identity map" do
2246
+ expect(Mongoid::IdentityMap[Post.collection_name][post_three.id]).to be_nil
2247
+ end
2248
+ end
2249
+ end
2250
+
2251
+ context "when including a has one" do
2252
+
2253
+ let!(:game_one) do
2254
+ person.create_game(name: "one")
2255
+ end
2256
+
2257
+ let!(:game_two) do
2258
+ person.create_game(name: "two")
2259
+ end
2260
+
2261
+ context "when the criteria has no options" do
2262
+
2263
+ before do
2264
+ Mongoid::IdentityMap.clear
2265
+ end
2266
+
2267
+ let!(:criteria) do
2268
+ Person.includes(:game)
2269
+ end
2270
+
2271
+ let(:context) do
2272
+ criteria.context
2273
+ end
2274
+
2275
+ before do
2276
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2277
+ end
2278
+
2279
+ let!(:documents) do
2280
+ criteria.entries
2281
+ end
2282
+
2283
+ it "returns the correct documents" do
2284
+ expect(documents).to eq([ person ])
2285
+ end
2286
+
2287
+ it "deletes the replaced document from the identity map" do
2288
+ expect(Mongoid::IdentityMap[Game.collection_name][game_one.id]).to be_nil
2289
+ end
2290
+
2291
+ it "inserts the second document into the identity map" do
2292
+ expect(Mongoid::IdentityMap[Game.collection_name][game_two.id]).to eq(game_two)
2293
+ end
2294
+
2295
+ context "when asking from map or db" do
2296
+
2297
+ let(:in_map) do
2298
+ Mongoid::IdentityMap[Game.collection_name][game_two.id]
2299
+ end
2300
+
2301
+ let(:game) do
2302
+ Game.where("person_id" => person.id).from_map_or_db
2303
+ end
2304
+
2305
+ it "returns the document from the map" do
2306
+ expect(game).to equal(in_map)
2307
+ end
2308
+ end
2309
+ end
2310
+
2311
+ context "when the criteria has limiting options" do
2312
+
2313
+ let!(:person_two) do
2314
+ Person.create
2315
+ end
2316
+
2317
+ let!(:game_three) do
2318
+ person_two.create_game(name: "Skyrim")
2319
+ end
2320
+
2321
+ before do
2322
+ Mongoid::IdentityMap.clear
2323
+ end
2324
+
2325
+ let!(:criteria) do
2326
+ Person.where(id: person.id).includes(:game).asc(:_id).limit(1)
2327
+ end
2328
+
2329
+ let(:context) do
2330
+ criteria.context
2331
+ end
2332
+
2333
+ before do
2334
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2335
+ end
2336
+
2337
+ let!(:documents) do
2338
+ criteria.entries
2339
+ end
2340
+
2341
+ it "returns the correct documents" do
2342
+ expect(documents).to eq([ person ])
2343
+ end
2344
+
2345
+ it "inserts the second document into the identity map" do
2346
+ expect(Mongoid::IdentityMap[Game.collection_name][game_two.id]).to eq(game_two)
2347
+ end
2348
+
2349
+ it "does not load the extra child into the map" do
2350
+ expect(Mongoid::IdentityMap[Game.collection_name][game_three.id]).to be_nil
2351
+ end
2352
+ end
2353
+ end
2354
+
2355
+ context "when including a belongs to" do
2356
+
2357
+ let(:person_two) do
2358
+ Person.create
2359
+ end
2360
+
2361
+ let!(:game_one) do
2362
+ person.create_game(name: "one")
2363
+ end
2364
+
2365
+ let!(:game_two) do
2366
+ person_two.create_game(name: "two")
2367
+ end
2368
+
2369
+ before do
2370
+ Mongoid::IdentityMap.clear
2371
+ end
2372
+
2373
+ context "when providing no options" do
2374
+
2375
+ let!(:criteria) do
2376
+ Game.includes(:person)
2377
+ end
2378
+
2379
+ let(:context) do
2380
+ criteria.context
2381
+ end
2382
+
2383
+ before do
2384
+ context.
2385
+ should_receive(:eager_load).
2386
+ with([ game_one, game_two ]).
2387
+ once.
2388
+ and_call_original
2389
+ end
2390
+
2391
+ let!(:documents) do
2392
+ criteria.entries
2393
+ end
2394
+
2395
+ it "returns the correct documents" do
2396
+ expect(criteria).to eq([ game_one, game_two ])
2397
+ end
2398
+
2399
+ it "inserts the first document into the identity map" do
2400
+ expect(Mongoid::IdentityMap[Person.collection_name][person.id]).to eq(person)
2401
+ end
2402
+
2403
+ it "inserts the second document into the identity map" do
2404
+ expect(Mongoid::IdentityMap[Person.collection_name][person_two.id]).to eq(person_two)
2405
+ end
2406
+ end
2407
+
2408
+ context "when the criteria has limiting options" do
2409
+
2410
+ let!(:criteria) do
2411
+ Game.where(id: game_one.id).includes(:person).asc(:_id).limit(1)
2412
+ end
2413
+
2414
+ let(:context) do
2415
+ criteria.context
2416
+ end
2417
+
2418
+ before do
2419
+ context.should_receive(:eager_load).with([ game_one ]).once.and_call_original
2420
+ end
2421
+
2422
+ let!(:documents) do
2423
+ criteria.entries
2424
+ end
2425
+
2426
+ it "returns the correct documents" do
2427
+ expect(documents).to eq([ game_one ])
2428
+ end
2429
+
2430
+ it "inserts the first document into the identity map" do
2431
+ expect(Mongoid::IdentityMap[Person.collection_name][person.id]).to eq(person)
2432
+ end
2433
+
2434
+ it "does not load the documents outside of the limit" do
2435
+ expect(Mongoid::IdentityMap[Person.collection_name][person_two.id]).to be_nil
2436
+ end
2437
+ end
2438
+ end
2439
+
2440
+ context "when including multiples in the same criteria" do
2441
+
2442
+ let!(:post_one) do
2443
+ person.posts.create(title: "one")
2444
+ end
2445
+
2446
+ let!(:post_two) do
2447
+ person.posts.create(title: "two")
2448
+ end
2449
+
2450
+ let!(:game_one) do
2451
+ person.create_game(name: "one")
2452
+ end
2453
+
2454
+ let!(:game_two) do
2455
+ person.create_game(name: "two")
2456
+ end
2457
+
2458
+ before do
2459
+ Mongoid::IdentityMap.clear
2460
+ end
2461
+
2462
+ let!(:criteria) do
2463
+ Person.includes(:posts, :game)
2464
+ end
2465
+
2466
+ let(:context) do
2467
+ criteria.context
2468
+ end
2469
+
2470
+ before do
2471
+ context.should_receive(:eager_load).with([ person ]).once.and_call_original
2472
+ end
2473
+
2474
+ let!(:documents) do
2475
+ criteria.entries
2476
+ end
2477
+
2478
+ it "returns the correct documents" do
2479
+ expect(criteria).to eq([ person ])
2480
+ end
2481
+
2482
+ it "inserts the first has many document into the identity map" do
2483
+ expect(Mongoid::IdentityMap[Post.collection_name][post_one.id]).to eq(post_one)
2484
+ end
2485
+
2486
+ it "inserts the second has many document into the identity map" do
2487
+ expect(Mongoid::IdentityMap[Post.collection_name][post_two.id]).to eq(post_two)
2488
+ end
2489
+
2490
+ it "removes the first has one document from the identity map" do
2491
+ expect(Mongoid::IdentityMap[Game.collection_name][game_one.id]).to be_nil
2492
+ end
2493
+
2494
+ it "inserts the second has one document into the identity map" do
2495
+ expect(Mongoid::IdentityMap[Game.collection_name][game_two.id]).to eq(game_two)
2496
+ end
2497
+ end
2498
+ end
2499
+
2500
+ describe "#inclusions" do
2501
+
2502
+ let(:criteria) do
2503
+ Band.includes(:records)
2504
+ end
2505
+
2506
+ let(:metadata) do
2507
+ Band.relations["records"]
2508
+ end
2509
+
2510
+ it "returns the inclusions" do
2511
+ expect(criteria.inclusions).to eq([ metadata ])
2512
+ end
2513
+ end
2514
+
2515
+ describe "#inclusions=" do
2516
+
2517
+ let(:criteria) do
2518
+ Band.all
2519
+ end
2520
+
2521
+ let(:metadata) do
2522
+ Band.relations["records"]
2523
+ end
2524
+
2525
+ before do
2526
+ criteria.inclusions = [ metadata ]
2527
+ end
2528
+
2529
+ it "sets the inclusions" do
2530
+ expect(criteria.inclusions).to eq([ metadata ])
2531
+ end
2532
+ end
2533
+
2534
+ describe "#lt" do
2535
+
2536
+ let!(:match) do
2537
+ Band.create(member_count: 1)
2538
+ end
2539
+
2540
+ let!(:non_match) do
2541
+ Band.create(member_count: 5)
2542
+ end
2543
+
2544
+ let(:criteria) do
2545
+ Band.lt(member_count: 4)
2546
+ end
2547
+
2548
+ it "returns the matching documents" do
2549
+ expect(criteria).to eq([ match ])
2550
+ end
2551
+ end
2552
+
2553
+ describe "#lte" do
2554
+
2555
+ let!(:match) do
2556
+ Band.create(member_count: 4)
2557
+ end
2558
+
2559
+ let!(:non_match) do
2560
+ Band.create(member_count: 5)
2561
+ end
2562
+
2563
+ let(:criteria) do
2564
+ Band.lte(member_count: 4)
2565
+ end
2566
+
2567
+ it "returns the matching documents" do
2568
+ expect(criteria).to eq([ match ])
2569
+ end
2570
+ end
2571
+
2572
+ describe "#map_reduce" do
2573
+
2574
+ let(:map) do
2575
+ %Q{
2576
+ function() {
2577
+ emit(this.name, { likes: this.likes });
2578
+ }}
2579
+ end
2580
+
2581
+ let(:reduce) do
2582
+ %Q{
2583
+ function(key, values) {
2584
+ var result = { likes: 0 };
2585
+ values.forEach(function(value) {
2586
+ result.likes += value.likes;
2587
+ });
2588
+ return result;
2589
+ }}
2590
+ end
2591
+
2592
+ let!(:depeche_mode) do
2593
+ Band.create(name: "Depeche Mode", likes: 200)
2594
+ end
2595
+
2596
+ let!(:tool) do
2597
+ Band.create(name: "Tool", likes: 100)
2598
+ end
2599
+
2600
+ let(:map_reduce) do
2601
+ Band.limit(2).map_reduce(map, reduce).out(inline: 1)
2602
+ end
2603
+
2604
+ it "returns the map/reduce results" do
2605
+ expect(map_reduce).to eq([
2606
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
2607
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
2608
+ ])
2609
+ end
2610
+ end
2611
+
2612
+ describe "#max" do
2613
+
2614
+ context "when provided a single field" do
2615
+
2616
+ let!(:depeche) do
2617
+ Band.create(name: "Depeche Mode", likes: 1000)
2618
+ end
2619
+
2620
+ let!(:tool) do
2621
+ Band.create(name: "Tool", likes: 500)
2622
+ end
2623
+
2624
+ let(:criteria) do
2625
+ Band.all
2626
+ end
2627
+
2628
+ context "when provided a symbol" do
2629
+
2630
+ let(:max) do
2631
+ criteria.max(:likes)
2632
+ end
2633
+
2634
+ it "returns the max of the provided field" do
2635
+ expect(max).to eq(1000)
2636
+ end
2637
+ end
2638
+
2639
+ context "when provided a block" do
2640
+
2641
+ let(:max) do
2642
+ criteria.max do |a, b|
2643
+ a.likes <=> b.likes
2644
+ end
2645
+ end
2646
+
2647
+ it "returns the document with the max value for the field" do
2648
+ expect(max).to eq(depeche)
2649
+ end
2650
+ end
2651
+ end
2652
+ end
2653
+
2654
+ describe "#max_distance" do
2655
+
2656
+ before do
2657
+ Bar.create_indexes
2658
+ end
2659
+
2660
+ let!(:match) do
2661
+ Bar.create(location: [ 52.30, 13.25 ])
2662
+ end
2663
+
2664
+ let!(:non_match) do
2665
+ Bar.create(location: [ 19.26, 99.70 ])
2666
+ end
2667
+
2668
+ let(:criteria) do
2669
+ Bar.near(location: [ 52, 13 ]).max_distance(location: 5)
2670
+ end
2671
+
2672
+ it "returns the matching documents" do
2673
+ expect(criteria).to eq([ match ])
2674
+ end
2675
+ end
2676
+
2677
+ describe "#merge" do
2678
+
2679
+ let(:band) do
2680
+ Band.new
2681
+ end
2682
+
2683
+ let(:criteria) do
2684
+ Band.scoped.where(name: "Depeche Mode").asc(:name)
2685
+ end
2686
+
2687
+ context "when merging with another criteria" do
2688
+
2689
+ let(:mergeable) do
2690
+ Band.includes(:records).tap do |crit|
2691
+ crit.documents = [ band ]
2692
+ end
2693
+ end
2694
+
2695
+ let(:metadata) do
2696
+ Band.relations["records"]
2697
+ end
2698
+
2699
+ let(:merged) do
2700
+ criteria.merge(mergeable)
2701
+ end
2702
+
2703
+ it "merges the selector" do
2704
+ expect(merged.selector).to eq({ "name" => "Depeche Mode" })
2705
+ end
2706
+
2707
+ it "merges the options" do
2708
+ expect(merged.options).to eq({ sort: { "name" => 1 }})
2709
+ end
2710
+
2711
+ it "merges the documents" do
2712
+ expect(merged.documents).to eq([ band ])
2713
+ end
2714
+
2715
+ it "merges the scoping options" do
2716
+ expect(merged.scoping_options).to eq([ nil, nil ])
2717
+ end
2718
+
2719
+ it "merges the inclusions" do
2720
+ expect(merged.inclusions).to eq([ metadata ])
2721
+ end
2722
+
2723
+ it "returns a new criteria" do
2724
+ expect(merged).to_not equal(criteria)
2725
+ end
2726
+ end
2727
+
2728
+ context "when merging with a hash" do
2729
+
2730
+ let(:mergeable) do
2731
+ { klass: Band, includes: [ :records ] }
2732
+ end
2733
+
2734
+ let(:metadata) do
2735
+ Band.relations["records"]
2736
+ end
2737
+
2738
+ let(:merged) do
2739
+ criteria.merge(mergeable)
2740
+ end
2741
+
2742
+ it "merges the selector" do
2743
+ expect(merged.selector).to eq({ "name" => "Depeche Mode" })
2744
+ end
2745
+
2746
+ it "merges the options" do
2747
+ expect(merged.options).to eq({ sort: { "name" => 1 }})
2748
+ end
2749
+
2750
+ it "merges the scoping options" do
2751
+ expect(merged.scoping_options).to eq([ nil, nil ])
2752
+ end
2753
+
2754
+ it "merges the inclusions" do
2755
+ expect(merged.inclusions).to eq([ metadata ])
2756
+ end
2757
+
2758
+ it "returns a new criteria" do
2759
+ expect(merged).to_not equal(criteria)
2760
+ end
2761
+ end
2762
+ end
2763
+
2764
+ describe "#merge!" do
2765
+
2766
+ let(:band) do
2767
+ Band.new
2768
+ end
2769
+
2770
+ let(:criteria) do
2771
+ Band.scoped.where(name: "Depeche Mode").asc(:name)
2772
+ end
2773
+
2774
+ let(:mergeable) do
2775
+ Band.includes(:records).tap do |crit|
2776
+ crit.documents = [ band ]
2777
+ end
2778
+ end
2779
+
2780
+ let(:metadata) do
2781
+ Band.relations["records"]
2782
+ end
2783
+
2784
+ let(:merged) do
2785
+ criteria.merge!(mergeable)
2786
+ end
2787
+
2788
+ it "merges the selector" do
2789
+ expect(merged.selector).to eq({ "name" => "Depeche Mode" })
2790
+ end
2791
+
2792
+ it "merges the options" do
2793
+ expect(merged.options).to eq({ sort: { "name" => 1 }})
2794
+ end
2795
+
2796
+ it "merges the documents" do
2797
+ expect(merged.documents).to eq([ band ])
2798
+ end
2799
+
2800
+ it "merges the scoping options" do
2801
+ expect(merged.scoping_options).to eq([ nil, nil ])
2802
+ end
2803
+
2804
+ it "merges the inclusions" do
2805
+ expect(merged.inclusions).to eq([ metadata ])
2806
+ end
2807
+
2808
+ it "returns the same criteria" do
2809
+ expect(merged).to equal(criteria)
2810
+ end
2811
+ end
2812
+
2813
+ describe "#min" do
2814
+
2815
+ context "when provided a single field" do
2816
+
2817
+ let!(:depeche) do
2818
+ Band.create(name: "Depeche Mode", likes: 1000)
2819
+ end
2820
+
2821
+ let!(:tool) do
2822
+ Band.create(name: "Tool", likes: 500)
2823
+ end
2824
+
2825
+ let(:criteria) do
2826
+ Band.all
2827
+ end
2828
+
2829
+ context "when provided a symbol" do
2830
+
2831
+ let(:min) do
2832
+ criteria.min(:likes)
2833
+ end
2834
+
2835
+ it "returns the min of the provided field" do
2836
+ expect(min).to eq(500)
2837
+ end
2838
+ end
2839
+
2840
+ context "when provided a block" do
2841
+
2842
+ let(:min) do
2843
+ criteria.min do |a, b|
2844
+ a.likes <=> b.likes
2845
+ end
2846
+ end
2847
+
2848
+ it "returns the document with the min value for the field" do
2849
+ expect(min).to eq(tool)
2850
+ end
2851
+ end
2852
+ end
2853
+ end
2854
+
2855
+ describe "#mod" do
2856
+
2857
+ let!(:match) do
2858
+ Band.create(member_count: 5)
2859
+ end
2860
+
2861
+ let!(:non_match) do
2862
+ Band.create(member_count: 2)
2863
+ end
2864
+
2865
+ let(:criteria) do
2866
+ Band.mod(member_count: [ 4, 1 ])
2867
+ end
2868
+
2869
+ it "returns the matching documents" do
2870
+ expect(criteria).to eq([ match ])
2871
+ end
2872
+ end
2873
+
2874
+ describe "#ne" do
2875
+
2876
+ let!(:match) do
2877
+ Band.create(name: "Depeche Mode")
2878
+ end
2879
+
2880
+ let!(:non_match) do
2881
+ Band.create(name: "Tool")
2882
+ end
2883
+
2884
+ let(:criteria) do
2885
+ Band.ne(name: "Tool")
2886
+ end
2887
+
2888
+ it "returns the matching documents" do
2889
+ expect(criteria).to eq([ match ])
2890
+ end
2891
+ end
2892
+
2893
+ describe "#near" do
2894
+
2895
+ before do
2896
+ Bar.create_indexes
2897
+ end
2898
+
2899
+ let!(:match) do
2900
+ Bar.create(location: [ 52.30, 13.25 ])
2901
+ end
2902
+
2903
+ let(:criteria) do
2904
+ Bar.near(location: [ 52, 13 ])
2905
+ end
2906
+
2907
+ it "returns the matching documents" do
2908
+ expect(criteria).to eq([ match ])
2909
+ end
2910
+ end
2911
+
2912
+ describe "#near_sphere" do
2913
+
2914
+ before do
2915
+ Bar.create_indexes
2916
+ end
2917
+
2918
+ let!(:match) do
2919
+ Bar.create(location: [ 52.30, 13.25 ])
2920
+ end
2921
+
2922
+ let(:criteria) do
2923
+ Bar.near_sphere(location: [ 52, 13 ])
2924
+ end
2925
+
2926
+ it "returns the matching documents" do
2927
+ expect(criteria).to eq([ match ])
2928
+ end
2929
+ end
2930
+
2931
+ describe "#nin" do
2932
+
2933
+ let!(:match) do
2934
+ Band.create(name: "Depeche Mode")
2935
+ end
2936
+
2937
+ let!(:non_match) do
2938
+ Band.create(name: "Tool")
2939
+ end
2940
+
2941
+ let(:criteria) do
2942
+ Band.nin(name: [ "Tool" ])
2943
+ end
2944
+
2945
+ it "returns the matching documents" do
2946
+ expect(criteria).to eq([ match ])
2947
+ end
2948
+ end
2949
+
2950
+ describe "#nor" do
2951
+
2952
+ let!(:match) do
2953
+ Band.create(name: "Depeche Mode")
2954
+ end
2955
+
2956
+ let!(:non_match) do
2957
+ Band.create(name: "Tool")
2958
+ end
2959
+
2960
+ let(:criteria) do
2961
+ Band.nor({ name: "Tool" }, { name: "New Order" })
2962
+ end
2963
+
2964
+ it "returns the matching documents" do
2965
+ expect(criteria).to eq([ match ])
2966
+ end
2967
+ end
2968
+
2969
+ describe "#only" do
2970
+
2971
+ let!(:band) do
2972
+ Band.create(name: "Depeche Mode", likes: 3, views: 10)
2973
+ end
2974
+
2975
+ context "when not using inheritance" do
2976
+
2977
+ context "when passing splat args" do
2978
+
2979
+ let(:criteria) do
2980
+ Band.only(:_id)
2981
+ end
2982
+
2983
+ it "limits the returned fields" do
2984
+ expect(criteria.first.name).to be_nil
2985
+ end
2986
+
2987
+ it "does not add _type to the fields" do
2988
+ expect(criteria.options[:fields]["_type"]).to be_nil
2989
+ end
2990
+ end
2991
+
2992
+ context "when passing an array" do
2993
+
2994
+ let(:criteria) do
2995
+ Band.only([ :name, :likes ])
2996
+ end
2997
+
2998
+ it "includes the limited fields" do
2999
+ expect(criteria.first.name).to_not be_nil
3000
+ end
3001
+
3002
+ it "excludes the non included fields" do
3003
+ expect(criteria.first.active).to be_nil
3004
+ end
3005
+
3006
+ it "does not add _type to the fields" do
3007
+ expect(criteria.options[:fields]["_type"]).to be_nil
3008
+ end
3009
+ end
3010
+
3011
+ context "when instantiating a class of another type inside the iteration" do
3012
+
3013
+ let(:criteria) do
3014
+ Band.only(:name)
3015
+ end
3016
+
3017
+ it "only limits the fields on the correct model" do
3018
+ criteria.each do |band|
3019
+ expect(Person.new.age).to eq(100)
3020
+ end
3021
+ end
3022
+ end
3023
+
3024
+ context "when instantiating a document not in the result set" do
3025
+
3026
+ let(:criteria) do
3027
+ Band.only(:name)
3028
+ end
3029
+
3030
+ it "only limits the fields on the correct criteria" do
3031
+ criteria.each do |band|
3032
+ expect(Band.new.active).to be_true
3033
+ end
3034
+ end
3035
+ end
3036
+
3037
+ context "when nesting a criteria within a criteria" do
3038
+
3039
+ let(:criteria) do
3040
+ Band.only(:name)
3041
+ end
3042
+
3043
+ it "only limits the fields on the correct criteria" do
3044
+ criteria.each do |band|
3045
+ Band.all.each do |b|
3046
+ expect(b.active).to be_true
3047
+ end
3048
+ end
3049
+ end
3050
+ end
3051
+ end
3052
+
3053
+ context "when using inheritance" do
3054
+
3055
+ let(:criteria) do
3056
+ Doctor.only(:_id)
3057
+ end
3058
+
3059
+ it "adds _type to the fields" do
3060
+ expect(criteria.options[:fields]["_type"]).to eq(1)
3061
+ end
3062
+ end
3063
+
3064
+ context "when limiting to embedded documents" do
3065
+
3066
+ context "when the embedded documents are aliased" do
3067
+
3068
+ let(:criteria) do
3069
+ Person.only(:phones)
3070
+ end
3071
+
3072
+ it "properly uses the database field name" do
3073
+ expect(criteria.options).to eq(fields: { "mobile_phones" => 1 })
3074
+ end
3075
+ end
3076
+ end
3077
+ end
3078
+
3079
+ [ :or, :any_of ].each do |method|
3080
+
3081
+ describe "\##{method}" do
3082
+
3083
+ let!(:match) do
3084
+ Band.create(name: "Depeche Mode")
3085
+ end
3086
+
3087
+ let!(:non_match) do
3088
+ Band.create(name: "Tool")
3089
+ end
3090
+
3091
+ context "when sending a normal $or criterion" do
3092
+
3093
+ let(:criteria) do
3094
+ Band.send(method, { name: "Depeche Mode" }, { name: "New Order" })
3095
+ end
3096
+
3097
+ it "returns the matching documents" do
3098
+ expect(criteria).to eq([ match ])
3099
+ end
3100
+ end
3101
+
3102
+ context "when matching against an id or other parameter" do
3103
+
3104
+ let(:criteria) do
3105
+ Band.send(method, { id: match.id }, { name: "New Order" })
3106
+ end
3107
+
3108
+ it "returns the matching documents" do
3109
+ expect(criteria).to eq([ match ])
3110
+ end
3111
+ end
3112
+ end
3113
+ end
3114
+
3115
+ describe "#pluck" do
3116
+
3117
+ let!(:depeche) do
3118
+ Band.create(name: "Depeche Mode", likes: 3)
3119
+ end
3120
+
3121
+ let!(:tool) do
3122
+ Band.create(name: "Tool", likes: 3)
3123
+ end
3124
+
3125
+ let!(:photek) do
3126
+ Band.create(name: "Photek", likes: 1)
3127
+ end
3128
+
3129
+ context "when the criteria matches" do
3130
+
3131
+ context "when there are no duplicate values" do
3132
+
3133
+ let(:criteria) do
3134
+ Band.where(:name.exists => true)
3135
+ end
3136
+
3137
+ let!(:plucked) do
3138
+ criteria.pluck(:name)
3139
+ end
3140
+
3141
+ it "returns the values" do
3142
+ expect(plucked).to eq([ "Depeche Mode", "Tool", "Photek" ])
3143
+ end
3144
+
3145
+ context "when subsequently executing the criteria without a pluck" do
3146
+
3147
+ it "does not limit the fields" do
3148
+ expect(criteria.first.likes).to eq(3)
3149
+ end
3150
+ end
3151
+ end
3152
+
3153
+ context "when plucking mult-fields" do
3154
+
3155
+ let(:plucked) do
3156
+ Band.where(:name.exists => true).pluck(:name, :likes)
3157
+ end
3158
+
3159
+ it "returns the values" do
3160
+ expect(plucked).to eq([ ["Depeche Mode", 3], ["Tool", 3], ["Photek", 1] ])
3161
+ end
3162
+ end
3163
+
3164
+ context "when there are duplicate values" do
3165
+
3166
+ let(:plucked) do
3167
+ Band.where(:name.exists => true).pluck(:likes)
3168
+ end
3169
+
3170
+ it "returns the duplicates" do
3171
+ expect(plucked).to eq([ 3, 3, 1 ])
3172
+ end
3173
+ end
3174
+ end
3175
+
3176
+ context "when the criteria does not match" do
3177
+
3178
+ let(:plucked) do
3179
+ Band.where(name: "New Order").pluck(:_id)
3180
+ end
3181
+
3182
+ it "returns an empty array" do
3183
+ expect(plucked).to be_empty
3184
+ end
3185
+ end
3186
+
3187
+ context "when plucking an aliased field" do
3188
+
3189
+ let(:plucked) do
3190
+ Band.all.pluck(:id)
3191
+ end
3192
+
3193
+ it "returns the field values" do
3194
+ expect(plucked).to eq([ depeche.id, tool.id, photek.id ])
3195
+ end
3196
+ end
3197
+
3198
+ context "when plucking a field that doesnt exist" do
3199
+
3200
+ context "when pluck one field" do
3201
+
3202
+ let(:plucked) do
3203
+ Band.all.pluck(:foo)
3204
+ end
3205
+
3206
+ it "returns a empty array" do
3207
+ expect(plucked).to eq([])
3208
+ end
3209
+ end
3210
+
3211
+ context "when pluck multiple fields" do
3212
+
3213
+ let(:plucked) do
3214
+ Band.all.pluck(:foo, :bar)
3215
+ end
3216
+
3217
+ it "returns a empty array" do
3218
+ expect(plucked).to eq([[], [], []])
3219
+ end
3220
+ end
3221
+ end
3222
+ end
3223
+
3224
+ describe "#respond_to?" do
3225
+
3226
+ let(:criteria) do
3227
+ described_class.new(Person)
3228
+ end
3229
+
3230
+ before do
3231
+ class Person
3232
+ def self.ages; self; end
3233
+ end
3234
+ end
3235
+
3236
+ context "when asking about a model public class method" do
3237
+
3238
+ it "returns true" do
3239
+ expect(criteria).to respond_to(:ages)
3240
+ end
3241
+ end
3242
+
3243
+ context "when asking about a model private class method" do
3244
+
3245
+ context "when including private methods" do
3246
+
3247
+ it "returns true" do
3248
+ expect(criteria.respond_to?(:for_ids, true)).to be_true
3249
+ end
3250
+ end
3251
+ end
3252
+
3253
+ context "when asking about a model class public instance method" do
3254
+
3255
+ it "returns true" do
3256
+ expect(criteria.respond_to?(:join)).to be_true
3257
+ end
3258
+ end
3259
+
3260
+ context "when asking about a model private instance method" do
3261
+
3262
+ context "when not including private methods" do
3263
+
3264
+ it "returns false" do
3265
+ expect(criteria).to_not respond_to(:fork)
3266
+ end
3267
+ end
3268
+
3269
+ context "when including private methods" do
3270
+
3271
+ it "returns true" do
3272
+ expect(criteria.respond_to?(:fork, true)).to be_true
3273
+ end
3274
+ end
3275
+ end
3276
+
3277
+ context "when asking about a criteria instance method" do
3278
+
3279
+ it "returns true" do
3280
+ expect(criteria).to respond_to(:context)
3281
+ end
3282
+ end
3283
+
3284
+ context "when asking about a private criteria instance method" do
3285
+
3286
+ context "when not including private methods" do
3287
+
3288
+ it "returns false" do
3289
+ expect(criteria).to_not respond_to(:puts)
3290
+ end
3291
+ end
3292
+
3293
+ context "when including private methods" do
3294
+
3295
+ it "returns true" do
3296
+ expect(criteria.respond_to?(:puts, true)).to be_true
3297
+ end
3298
+ end
3299
+ end
3300
+ end
3301
+
3302
+ describe "#sort" do
3303
+
3304
+ let!(:depeche) do
3305
+ Band.create(name: "Depeche Mode", likes: 1000)
3306
+ end
3307
+
3308
+ let!(:tool) do
3309
+ Band.create(name: "Tool", likes: 500)
3310
+ end
3311
+
3312
+ let(:sorted) do
3313
+ Band.all.sort do |a, b|
3314
+ b.name <=> a.name
3315
+ end
3316
+ end
3317
+
3318
+ it "sorts the results in memory" do
3319
+ expect(sorted).to eq([ tool, depeche ])
3320
+ end
3321
+ end
3322
+
3323
+ describe "#sum" do
3324
+
3325
+ context "when provided a single field" do
3326
+
3327
+ let!(:depeche) do
3328
+ Band.create(name: "Depeche Mode", likes: 1000)
3329
+ end
3330
+
3331
+ let!(:tool) do
3332
+ Band.create(name: "Tool", likes: 500)
3333
+ end
3334
+
3335
+ let(:criteria) do
3336
+ Band.all
3337
+ end
3338
+
3339
+ context "when provided a symbol" do
3340
+
3341
+ let(:sum) do
3342
+ criteria.sum(:likes)
3343
+ end
3344
+
3345
+ it "returns the sum of the provided field" do
3346
+ expect(sum).to eq(1500)
3347
+ end
3348
+ end
3349
+
3350
+ context "when provided a block" do
3351
+
3352
+ let(:sum) do
3353
+ criteria.sum(&:likes)
3354
+ end
3355
+
3356
+ it "returns the sum for the provided block" do
3357
+ expect(sum).to eq(1500)
3358
+ end
3359
+ end
3360
+ end
3361
+ end
3362
+
3363
+ describe "#to_ary" do
3364
+
3365
+ let!(:band) do
3366
+ Band.create(name: "Depeche Mode")
3367
+ end
3368
+
3369
+ let(:criteria) do
3370
+ Band.where(name: "Depeche Mode")
3371
+ end
3372
+
3373
+ it "returns the executed criteria" do
3374
+ expect(criteria.to_ary).to eq([ band ])
3375
+ end
3376
+ end
3377
+
3378
+ describe "#extras with a hint" do
3379
+
3380
+ let!(:band) do
3381
+ Band.create(name: "Depeche Mode")
3382
+ end
3383
+
3384
+ let(:criteria) do
3385
+ Band.where(name: "Depeche Mode").extras(:hint => {:bad_hint => 1})
3386
+ end
3387
+
3388
+ it "executes the criteria while properly giving the hint to Mongo" do
3389
+ expect { criteria.to_ary }.to raise_error(Moped::Errors::QueryFailure, %r{failed with error 10113: "bad hint"})
3390
+ end
3391
+ end
3392
+
3393
+ describe "#hint" do
3394
+
3395
+ let!(:band) do
3396
+ Band.create(name: "Depeche Mode")
3397
+ end
3398
+
3399
+ let(:criteria) do
3400
+ Band.where(name: "Depeche Mode").hint(bad_hint: 1)
3401
+ end
3402
+
3403
+ it "executes the criteria while properly giving the hint to Mongo" do
3404
+ expect { criteria.to_ary }.to raise_error(Moped::Errors::QueryFailure, %r{failed with error 10113: "bad hint"})
3405
+ end
3406
+ end
3407
+
3408
+ describe "#max_scan" do
3409
+ let!(:band) do
3410
+ Band.create(name: "Depeche Mode")
3411
+ end
3412
+
3413
+ let!(:band2) do
3414
+ Band.create(name: "Tool")
3415
+ end
3416
+
3417
+ let(:criteria) do
3418
+ Band.where({}).max_scan(1)
3419
+ end
3420
+
3421
+ it "executes the criteria while properly giving the max scan to Mongo" do
3422
+ expect(criteria.to_ary).to eq [band]
3423
+ end
3424
+ end
3425
+
3426
+ describe "#text_search" do
3427
+
3428
+ let(:criteria) do
3429
+ Word.all
3430
+ end
3431
+
3432
+ before do
3433
+ Word.with(database: "admin").mongo_session.command(setParameter: 1, textSearchEnabled: true)
3434
+ Word.create_indexes
3435
+ Word.with(safe: true).create!(name: "phase", origin: "latin")
3436
+ end
3437
+
3438
+ after(:all) do
3439
+ Word.remove_indexes
3440
+ end
3441
+
3442
+ let(:search) do
3443
+ criteria.text_search("phase")
3444
+ end
3445
+
3446
+ it "returns all fields" do
3447
+ expect(search.first.origin).to eq("latin")
3448
+ end
3449
+ end
3450
+
3451
+ describe "#to_criteria" do
3452
+
3453
+ let(:criteria) do
3454
+ Band.all
3455
+ end
3456
+
3457
+ it "returns self" do
3458
+ expect(criteria.to_criteria).to eq(criteria)
3459
+ end
3460
+ end
3461
+
3462
+ describe "#to_proc" do
3463
+
3464
+ let(:criteria) do
3465
+ Band.all
3466
+ end
3467
+
3468
+ it "returns a proc" do
3469
+ expect(criteria.to_proc).to be_a(Proc)
3470
+ end
3471
+
3472
+ it "wraps the criteria in the proc" do
3473
+ expect(criteria.to_proc[]).to eq(criteria)
3474
+ end
3475
+ end
3476
+
3477
+ describe "#type" do
3478
+
3479
+ context "when the type is a string" do
3480
+
3481
+ let!(:browser) do
3482
+ Browser.create
3483
+ end
3484
+
3485
+ let(:criteria) do
3486
+ Canvas.all.type("Browser")
3487
+ end
3488
+
3489
+ it "returns documents with the provided type" do
3490
+ expect(criteria).to eq([ browser ])
3491
+ end
3492
+ end
3493
+
3494
+ context "when the type is an Array of type" do
3495
+
3496
+ let!(:browser) do
3497
+ Firefox.create
3498
+ end
3499
+
3500
+ let(:criteria) do
3501
+ Canvas.all.type([ "Browser", "Firefox" ])
3502
+ end
3503
+
3504
+ it "returns documents with the provided types" do
3505
+ expect(criteria).to eq([ browser ])
3506
+ end
3507
+ end
3508
+ end
3509
+
3510
+ describe "#where" do
3511
+
3512
+ let!(:match) do
3513
+ Band.create(name: "Depeche Mode")
3514
+ end
3515
+
3516
+ let!(:non_match) do
3517
+ Band.create(name: "Tool")
3518
+ end
3519
+
3520
+ context "when provided a string" do
3521
+
3522
+ context "when the criteria is embedded" do
3523
+
3524
+ it "raises an error" do
3525
+ expect {
3526
+ match.records.where("this.name == null")
3527
+ }.to raise_error(Mongoid::Errors::UnsupportedJavascript)
3528
+ end
3529
+ end
3530
+
3531
+ context "when the criteria is not embedded" do
3532
+
3533
+ let(:criteria) do
3534
+ Band.where("this.name == 'Depeche Mode'")
3535
+ end
3536
+
3537
+ it "returns the matching documents" do
3538
+ expect(criteria).to eq([ match ])
3539
+ end
3540
+ end
3541
+ end
3542
+
3543
+ context "when provided criterion" do
3544
+
3545
+ context "when the criteria is standard" do
3546
+
3547
+ let(:criteria) do
3548
+ Band.where(name: "Depeche Mode")
3549
+ end
3550
+
3551
+ it "returns the matching documents" do
3552
+ expect(criteria).to eq([ match ])
3553
+ end
3554
+ end
3555
+
3556
+ context "when the criteria is an exact fk array match" do
3557
+
3558
+ let(:id_one) do
3559
+ Moped::BSON::ObjectId.new
3560
+ end
3561
+
3562
+ let(:id_two) do
3563
+ Moped::BSON::ObjectId.new
3564
+ end
3565
+
3566
+ let(:criteria) do
3567
+ Account.where(agent_ids: [ id_one, id_two ])
3568
+ end
3569
+
3570
+ it "does not wrap the array in another array" do
3571
+ expect(criteria.selector).to eq({ "agent_ids" => [ id_one, id_two ]})
3572
+ end
3573
+ end
3574
+ end
3575
+ end
3576
+
3577
+ describe "#for_js" do
3578
+
3579
+ let!(:match) do
3580
+ Band.create(name: "Depeche Mode")
3581
+ end
3582
+
3583
+ context "when the code has no scope" do
3584
+
3585
+ let(:criteria) do
3586
+ Band.for_js("this.name == 'Depeche Mode'")
3587
+ end
3588
+
3589
+ it "returns the matching documents" do
3590
+ expect(criteria).to eq([ match ])
3591
+ end
3592
+ end
3593
+
3594
+ context "when the code has scope" do
3595
+
3596
+ let(:criteria) do
3597
+ Band.for_js("this.name == param", param: "Depeche Mode")
3598
+ end
3599
+
3600
+ it "returns the matching documents" do
3601
+ expect(criteria).to eq([ match ])
3602
+ end
3603
+ end
3604
+ end
3605
+
3606
+ describe "#method_missing" do
3607
+
3608
+ let(:criteria) do
3609
+ Person.all
3610
+ end
3611
+
3612
+ context "when the method exists on the class" do
3613
+
3614
+ before do
3615
+ Person.should_receive(:minor).and_call_original
3616
+ end
3617
+
3618
+ it "calls the method on the class" do
3619
+ expect(criteria.minor).to be_empty
3620
+ end
3621
+ end
3622
+
3623
+ context "when the method exists on the criteria" do
3624
+
3625
+ before do
3626
+ criteria.should_receive(:to_criteria).and_call_original
3627
+ end
3628
+
3629
+ it "calls the method on the criteria" do
3630
+ expect(criteria.to_criteria).to eq(criteria)
3631
+ end
3632
+ end
3633
+
3634
+ context "when the method exists on array" do
3635
+
3636
+ before do
3637
+ criteria.should_receive(:entries).and_call_original
3638
+ end
3639
+
3640
+ it "calls the method on the criteria" do
3641
+ expect(criteria.at(0)).to be_nil
3642
+ end
3643
+ end
3644
+
3645
+ context "when the method does not exist" do
3646
+
3647
+ before do
3648
+ criteria.should_receive(:entries).never
3649
+ end
3650
+
3651
+ it "raises an error" do
3652
+ expect {
3653
+ criteria.to_hash
3654
+ }.to raise_error(NoMethodError)
3655
+ end
3656
+ end
3657
+ end
3658
+
3659
+ describe "#uniq" do
3660
+
3661
+ let!(:band_one) do
3662
+ Band.create(name: "New Order")
3663
+ end
3664
+
3665
+ let!(:band_two) do
3666
+ Band.create(name: "New Order")
3667
+ end
3668
+
3669
+ let(:criteria) do
3670
+ Band.all
3671
+ end
3672
+
3673
+ it "passes the block through method_missing" do
3674
+ expect(criteria.uniq(&:name)).to eq([ band_one ])
3675
+ end
3676
+ end
3677
+
3678
+ describe "#with" do
3679
+
3680
+ let!(:criteria) do
3681
+ Band.where(name: "Depeche Mode").with(collection: "artists")
3682
+ end
3683
+
3684
+ it "retains the criteria selection" do
3685
+ expect(criteria.selector).to eq("name" => "Depeche Mode")
3686
+ end
3687
+
3688
+ it "sets the persistence options" do
3689
+ expect(criteria.persistence_options).to eq(collection: "artists")
3690
+ end
3691
+ end
3692
+
3693
+ describe "#within_box" do
3694
+
3695
+ before do
3696
+ Bar.create_indexes
3697
+ end
3698
+
3699
+ let!(:match) do
3700
+ Bar.create(location: [ 52.30, 13.25 ])
3701
+ end
3702
+
3703
+ let(:criteria) do
3704
+ Bar.within_box(location: [[ 50, 10 ], [ 60, 20 ]])
3705
+ end
3706
+
3707
+ it "returns the matching documents" do
3708
+ expect(criteria).to eq([ match ])
3709
+ end
3710
+ end
3711
+
3712
+ describe "#within_circle" do
3713
+
3714
+ before do
3715
+ Bar.create_indexes
3716
+ end
3717
+
3718
+ let!(:match) do
3719
+ Bar.create(location: [ 52.30, 13.25 ])
3720
+ end
3721
+
3722
+ let(:criteria) do
3723
+ Bar.within_circle(location: [[ 52, 13 ], 0.5 ])
3724
+ end
3725
+
3726
+ it "returns the matching documents" do
3727
+ expect(criteria).to eq([ match ])
3728
+ end
3729
+ end
3730
+
3731
+ describe "#within_polygon" do
3732
+
3733
+ before do
3734
+ Bar.create_indexes
3735
+ end
3736
+
3737
+ let!(:match) do
3738
+ Bar.create(location: [ 52.30, 13.25 ])
3739
+ end
3740
+
3741
+ let(:criteria) do
3742
+ Bar.within_polygon(
3743
+ location: [[ 50, 10 ], [ 50, 20 ], [ 60, 20 ], [ 60, 10 ]]
3744
+ )
3745
+ end
3746
+
3747
+ it "returns the matching documents" do
3748
+ expect(criteria).to eq([ match ])
3749
+ end
3750
+ end
3751
+
3752
+ describe "#within_spherical_circle" do
3753
+
3754
+ before do
3755
+ Bar.create_indexes
3756
+ end
3757
+
3758
+ let!(:match) do
3759
+ Bar.create(location: [ 52.30, 13.25 ])
3760
+ end
3761
+
3762
+ let(:criteria) do
3763
+ Bar.within_spherical_circle(location: [[ 52, 13 ], 0.5 ])
3764
+ end
3765
+
3766
+ it "returns the matching documents" do
3767
+ expect(criteria).to eq([ match ])
3768
+ end
3769
+ end
3770
+
3771
+ describe "#with_size" do
3772
+
3773
+ let!(:match) do
3774
+ Band.create(genres: [ "electro", "dub" ])
3775
+ end
3776
+
3777
+ let!(:non_match) do
3778
+ Band.create(genres: [ "house" ])
3779
+ end
3780
+
3781
+ let(:criteria) do
3782
+ Band.with_size(genres: 2)
3783
+ end
3784
+
3785
+ it "returns the matching documents" do
3786
+ expect(criteria).to eq([ match ])
3787
+ end
3788
+ end
3789
+
3790
+ describe "#with_type" do
3791
+
3792
+ let!(:match) do
3793
+ Band.create(name: "Depeche Mode")
3794
+ end
3795
+
3796
+ let(:criteria) do
3797
+ Band.with_type(name: 2)
3798
+ end
3799
+
3800
+ it "returns the matching documents" do
3801
+ expect(criteria).to eq([ match ])
3802
+ end
3803
+ end
3804
+
3805
+ describe "#without" do
3806
+
3807
+ context "when omitting to embedded documents" do
3808
+
3809
+ context "when the embedded documents are aliased" do
3810
+
3811
+ let(:criteria) do
3812
+ Person.without(:phones)
3813
+ end
3814
+
3815
+ it "properly uses the database field name" do
3816
+ expect(criteria.options).to eq(fields: { "mobile_phones" => 0 })
3817
+ end
3818
+ end
3819
+ end
3820
+ end
3821
+ end