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,1843 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Contextual::Mongo do
4
+
5
+ [ :blank?, :empty? ].each do |method|
6
+
7
+ describe "##{method}" do
8
+
9
+ before do
10
+ Band.create(name: "Depeche Mode")
11
+ end
12
+
13
+ context "when the count is zero" do
14
+
15
+ let(:criteria) do
16
+ Band.where(name: "New Order")
17
+ end
18
+
19
+ let(:context) do
20
+ described_class.new(criteria)
21
+ end
22
+
23
+ it "returns true" do
24
+ expect(context.send(method)).to be_true
25
+ end
26
+ end
27
+
28
+ context "when the count is greater than zero" do
29
+
30
+ let(:criteria) do
31
+ Band.where(name: "Depeche Mode")
32
+ end
33
+
34
+ let(:context) do
35
+ described_class.new(criteria)
36
+ end
37
+
38
+ it "returns false" do
39
+ expect(context.send(method)).to be_false
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#cached?" do
46
+
47
+ context "when the criteria is cached" do
48
+
49
+ let(:criteria) do
50
+ Band.all.cache
51
+ end
52
+
53
+ let(:context) do
54
+ described_class.new(criteria)
55
+ end
56
+
57
+ it "returns true" do
58
+ expect(context).to be_cached
59
+ end
60
+ end
61
+
62
+ context "when the criteria is not cached" do
63
+
64
+ let(:criteria) do
65
+ Band.all
66
+ end
67
+
68
+ let(:context) do
69
+ described_class.new(criteria)
70
+ end
71
+
72
+ it "returns false" do
73
+ expect(context).to_not be_cached
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "#count" do
79
+
80
+ let!(:depeche) do
81
+ Band.create(name: "Depeche Mode")
82
+ end
83
+
84
+ let!(:new_order) do
85
+ Band.create(name: "New Order")
86
+ end
87
+
88
+ let(:criteria) do
89
+ Band.where(name: "Depeche Mode")
90
+ end
91
+
92
+ context "when no arguments are provided" do
93
+
94
+ let(:context) do
95
+ described_class.new(criteria)
96
+ end
97
+
98
+ it "returns the number of documents that match" do
99
+ expect(context.count).to eq(1)
100
+ end
101
+ end
102
+
103
+ context "when context is cached" do
104
+
105
+ let(:context) do
106
+ described_class.new(criteria.cache)
107
+ end
108
+
109
+ before do
110
+ context.query.should_receive(:count).once.and_return(1)
111
+ end
112
+
113
+ it "returns the count cached value after first call" do
114
+ 2.times { expect(context.count).to eq(1) }
115
+ end
116
+ end
117
+
118
+ context "when provided a document" do
119
+
120
+ let(:context) do
121
+ described_class.new(criteria)
122
+ end
123
+
124
+ let(:count) do
125
+ context.count(depeche)
126
+ end
127
+
128
+ it "returns the number of documents that match" do
129
+ expect(count).to eq(1)
130
+ end
131
+ end
132
+
133
+ context "when provided a block" do
134
+
135
+ let(:context) do
136
+ described_class.new(criteria)
137
+ end
138
+
139
+ let(:count) do
140
+ context.count do |doc|
141
+ doc.likes.nil?
142
+ end
143
+ end
144
+
145
+ it "returns the number of documents that match" do
146
+ expect(count).to eq(1)
147
+ end
148
+
149
+ context "and a limit true" do
150
+
151
+ before do
152
+ 2.times { Band.create(name: "Depeche Mode", likes: 1) }
153
+ end
154
+
155
+ let(:count) do
156
+ context.count(true) do |doc|
157
+ doc.likes.nil?
158
+ end
159
+ end
160
+
161
+ it "returns the number of documents that match" do
162
+ expect(count).to eq(1)
163
+ end
164
+ end
165
+ end
166
+
167
+ context "when provided limit true" do
168
+
169
+ before do
170
+ 2.times { Band.create(name: "Depeche Mode") }
171
+ end
172
+
173
+ let(:context) do
174
+ described_class.new(criteria.limit(2))
175
+ end
176
+
177
+ let(:count) do
178
+ context.count(true)
179
+ end
180
+
181
+ it "returns the number of documents that match" do
182
+ expect(count).to eq(2)
183
+ end
184
+ end
185
+ end
186
+
187
+ [ :delete, :delete_all ].each do |method|
188
+
189
+ describe "##{method}" do
190
+
191
+ let!(:depeche_mode) do
192
+ Band.create(name: "Depeche Mode")
193
+ end
194
+
195
+ let!(:new_order) do
196
+ Band.create(name: "New Order")
197
+ end
198
+
199
+ context "when the selector is contraining" do
200
+
201
+ let(:criteria) do
202
+ Band.where(name: "Depeche Mode")
203
+ end
204
+
205
+ let(:context) do
206
+ described_class.new(criteria)
207
+ end
208
+
209
+ let!(:deleted) do
210
+ context.send(method)
211
+ end
212
+
213
+ it "deletes the matching documents" do
214
+ expect(Band.find(new_order.id)).to eq(new_order)
215
+ end
216
+
217
+ it "deletes the correct number of documents" do
218
+ expect(Band.count).to eq(1)
219
+ end
220
+
221
+ it "returns the number of documents deleted" do
222
+ expect(deleted).to eq(1)
223
+ end
224
+ end
225
+
226
+ context "when the selector is not contraining" do
227
+
228
+ let(:criteria) do
229
+ Band.all
230
+ end
231
+
232
+ let(:context) do
233
+ described_class.new(criteria)
234
+ end
235
+
236
+ before do
237
+ context.send(method)
238
+ end
239
+
240
+ it "deletes all the documents" do
241
+ expect(Band.count).to eq(0)
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ [ :destroy, :destroy_all ].each do |method|
248
+
249
+ describe "##{method}" do
250
+
251
+ let!(:depeche_mode) do
252
+ Band.create(name: "Depeche Mode")
253
+ end
254
+
255
+ let!(:new_order) do
256
+ Band.create(name: "New Order")
257
+ end
258
+
259
+ context "when the selector is contraining" do
260
+
261
+ let(:criteria) do
262
+ Band.where(name: "Depeche Mode")
263
+ end
264
+
265
+ let(:context) do
266
+ described_class.new(criteria)
267
+ end
268
+
269
+ let!(:destroyed) do
270
+ context.send(method)
271
+ end
272
+
273
+ it "destroys the matching documents" do
274
+ expect(Band.find(new_order.id)).to eq(new_order)
275
+ end
276
+
277
+ it "destroys the correct number of documents" do
278
+ expect(Band.count).to eq(1)
279
+ end
280
+
281
+ it "returns the number of documents destroyed" do
282
+ expect(destroyed).to eq(1)
283
+ end
284
+ end
285
+
286
+ context "when the selector is not contraining" do
287
+
288
+ let(:criteria) do
289
+ Band.all
290
+ end
291
+
292
+ let(:context) do
293
+ described_class.new(criteria)
294
+ end
295
+
296
+ before do
297
+ context.send(method)
298
+ end
299
+
300
+ it "destroys all the documents" do
301
+ expect(Band.count).to eq(0)
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+ describe "#distinct" do
308
+
309
+ before do
310
+ Band.create(name: "Depeche Mode", years: 30)
311
+ Band.create(name: "New Order", years: 25)
312
+ end
313
+
314
+ context "when limiting the result set" do
315
+
316
+ let(:criteria) do
317
+ Band.where(name: "Depeche Mode")
318
+ end
319
+
320
+ let(:context) do
321
+ described_class.new(criteria)
322
+ end
323
+
324
+ it "returns the distinct matching fields" do
325
+ expect(context.distinct(:name)).to eq([ "Depeche Mode" ])
326
+ end
327
+ end
328
+
329
+ context "when not limiting the result set" do
330
+
331
+ let(:criteria) do
332
+ Band.criteria
333
+ end
334
+
335
+ let(:context) do
336
+ described_class.new(criteria)
337
+ end
338
+
339
+ it "returns the distinct field values" do
340
+ expect(context.distinct(:name)).to eq([ "Depeche Mode", "New Order" ])
341
+ end
342
+ end
343
+
344
+ context "when providing an aliased field" do
345
+
346
+ let(:criteria) do
347
+ Band.criteria
348
+ end
349
+
350
+ let(:context) do
351
+ described_class.new(criteria)
352
+ end
353
+
354
+ it "returns the distinct field values" do
355
+ expect(context.distinct(:years)).to eq([ 30, 25 ])
356
+ end
357
+ end
358
+ end
359
+
360
+ describe "#each" do
361
+
362
+ before do
363
+ Band.create(name: "Depeche Mode")
364
+ end
365
+
366
+ let(:criteria) do
367
+ Band.where(name: "Depeche Mode")
368
+ end
369
+
370
+ let(:context) do
371
+ described_class.new(criteria)
372
+ end
373
+
374
+ context "when providing a block" do
375
+
376
+ it "yields mongoid documents to the block" do
377
+ context.each do |doc|
378
+ expect(doc).to be_a(Mongoid::Document)
379
+ end
380
+ end
381
+
382
+ it "iterates over the matching documents" do
383
+ context.each do |doc|
384
+ expect(doc.name).to eq("Depeche Mode")
385
+ end
386
+ end
387
+
388
+ it "returns self" do
389
+ expect(context.each{}).to be(context)
390
+ end
391
+ end
392
+
393
+ context "when no block is provided" do
394
+
395
+ let(:enum) do
396
+ context.each
397
+ end
398
+
399
+ it "returns an enumerator" do
400
+ expect(enum).to be_a(Enumerator)
401
+ end
402
+
403
+ context "when iterating over the enumerator" do
404
+
405
+ context "when iterating with each" do
406
+
407
+ it "yields mongoid documents to the block" do
408
+ enum.each do |doc|
409
+ expect(doc).to be_a(Mongoid::Document)
410
+ end
411
+ end
412
+ end
413
+
414
+ context "when iterating with next" do
415
+
416
+ it "yields mongoid documents" do
417
+ expect(enum.next).to be_a(Mongoid::Document)
418
+ end
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ describe "#eager_load" do
425
+
426
+ let(:criteria) do
427
+ Person.includes(:game)
428
+ end
429
+
430
+ let(:context) do
431
+ described_class.new(criteria)
432
+ end
433
+
434
+ context "when no documents are returned" do
435
+
436
+ let(:game_metadata) do
437
+ Person.reflect_on_association(:game)
438
+ end
439
+
440
+ it "does not make any additional database queries" do
441
+ game_metadata.should_receive(:eager_load).never
442
+ context.send(:eager_load, [])
443
+ end
444
+ end
445
+ end
446
+
447
+ describe "#exists?" do
448
+
449
+ before do
450
+ Band.create(name: "Depeche Mode")
451
+ end
452
+
453
+ context "when the count is zero" do
454
+
455
+ let(:criteria) do
456
+ Band.where(name: "New Order")
457
+ end
458
+
459
+ let(:context) do
460
+ described_class.new(criteria)
461
+ end
462
+
463
+ it "returns false" do
464
+ expect(context).to_not be_exists
465
+ end
466
+ end
467
+
468
+ context "when the count is greater than zero" do
469
+
470
+ let(:criteria) do
471
+ Band.where(name: "Depeche Mode")
472
+ end
473
+
474
+ let(:context) do
475
+ described_class.new(criteria)
476
+ end
477
+
478
+ it "returns true" do
479
+ expect(context).to be_exists
480
+ end
481
+ end
482
+
483
+ context "when caching is not enabled" do
484
+
485
+ let(:criteria) do
486
+ Band.where(name: "Depeche Mode")
487
+ end
488
+
489
+ let(:context) do
490
+ described_class.new(criteria)
491
+ end
492
+
493
+ context "when exists? already called" do
494
+
495
+ before do
496
+ context.exists?
497
+ end
498
+
499
+ it "hits the database again" do
500
+ context.should_receive(:query).once.and_call_original
501
+ context.should be_exists
502
+ end
503
+ end
504
+ end
505
+
506
+ context "when caching is enabled" do
507
+
508
+ let(:criteria) do
509
+ Band.where(name: "Depeche Mode").cache
510
+ end
511
+
512
+ let(:context) do
513
+ described_class.new(criteria)
514
+ end
515
+
516
+ context "when the cache is loaded" do
517
+
518
+ before do
519
+ context.to_a
520
+ end
521
+
522
+ it "does not hit the database" do
523
+ context.should_receive(:query).never
524
+ expect(context).to be_exists
525
+ end
526
+ end
527
+
528
+ context "when the cache is not loaded" do
529
+
530
+ context "when a count has been executed" do
531
+
532
+ before do
533
+ context.count
534
+ end
535
+
536
+ it "does not hit the database" do
537
+ context.should_receive(:query).never
538
+ expect(context).to be_exists
539
+ end
540
+ end
541
+ end
542
+ end
543
+ end
544
+
545
+ describe "#explain" do
546
+
547
+ let(:criteria) do
548
+ Band.where(name: "Depeche Mode")
549
+ end
550
+
551
+ let(:context) do
552
+ described_class.new(criteria)
553
+ end
554
+
555
+ it "returns the criteria explain path" do
556
+ expect(context.explain["cursor"]).to eq("BasicCursor")
557
+ end
558
+ end
559
+
560
+ describe "#find_and_modify" do
561
+
562
+ let!(:depeche) do
563
+ Band.create(name: "Depeche Mode")
564
+ end
565
+
566
+ let!(:tool) do
567
+ Band.create(name: "Tool")
568
+ end
569
+
570
+ context "when the selector matches" do
571
+
572
+ context "when not providing options" do
573
+
574
+ let(:criteria) do
575
+ Band.where(name: "Depeche Mode")
576
+ end
577
+
578
+ let(:context) do
579
+ described_class.new(criteria)
580
+ end
581
+
582
+ let!(:result) do
583
+ context.find_and_modify("$inc" => { likes: 1 })
584
+ end
585
+
586
+ it "returns the first matching document" do
587
+ expect(result).to eq(depeche)
588
+ end
589
+
590
+ it "updates the document in the database" do
591
+ expect(depeche.reload.likes).to eq(1)
592
+ end
593
+ end
594
+
595
+ context "when sorting" do
596
+
597
+ let(:criteria) do
598
+ Band.desc(:name)
599
+ end
600
+
601
+ let(:context) do
602
+ described_class.new(criteria)
603
+ end
604
+
605
+ let!(:result) do
606
+ context.find_and_modify("$inc" => { likes: 1 })
607
+ end
608
+
609
+ it "returns the first matching document" do
610
+ expect(result).to eq(tool)
611
+ end
612
+
613
+ it "updates the document in the database" do
614
+ expect(tool.reload.likes).to eq(1)
615
+ end
616
+ end
617
+
618
+ context "when limiting fields" do
619
+
620
+ let(:criteria) do
621
+ Band.only(:_id)
622
+ end
623
+
624
+ let(:context) do
625
+ described_class.new(criteria)
626
+ end
627
+
628
+ let!(:result) do
629
+ context.find_and_modify("$inc" => { likes: 1 })
630
+ end
631
+
632
+ it "returns the first matching document" do
633
+ expect(result).to eq(depeche)
634
+ end
635
+
636
+ it "limits the returned fields" do
637
+ expect(result.name).to be_nil
638
+ end
639
+
640
+ it "updates the document in the database" do
641
+ expect(depeche.reload.likes).to eq(1)
642
+ end
643
+ end
644
+
645
+ context "when returning new" do
646
+
647
+ let(:criteria) do
648
+ Band.where(name: "Depeche Mode")
649
+ end
650
+
651
+ let(:context) do
652
+ described_class.new(criteria)
653
+ end
654
+
655
+ let!(:result) do
656
+ context.find_and_modify({ "$inc" => { likes: 1 }}, new: true)
657
+ end
658
+
659
+ it "returns the first matching document" do
660
+ expect(result).to eq(depeche)
661
+ end
662
+
663
+ it "returns the updated document" do
664
+ expect(result.likes).to eq(1)
665
+ end
666
+ end
667
+
668
+ context "when removing" do
669
+
670
+ let(:criteria) do
671
+ Band.where(name: "Depeche Mode")
672
+ end
673
+
674
+ let(:context) do
675
+ described_class.new(criteria)
676
+ end
677
+
678
+ let!(:result) do
679
+ context.find_and_modify({}, remove: true)
680
+ end
681
+
682
+ it "returns the first matching document" do
683
+ expect(result).to eq(depeche)
684
+ end
685
+
686
+ it "deletes the document from the database" do
687
+ expect {
688
+ depeche.reload
689
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
690
+ end
691
+ end
692
+ end
693
+
694
+ context "when the selector does not match" do
695
+
696
+ let(:criteria) do
697
+ Band.where(name: "Placebo")
698
+ end
699
+
700
+ let(:context) do
701
+ described_class.new(criteria)
702
+ end
703
+
704
+ let(:result) do
705
+ context.find_and_modify("$inc" => { likes: 1 })
706
+ end
707
+
708
+ it "returns nil" do
709
+ expect(result).to be_nil
710
+ end
711
+ end
712
+ end
713
+
714
+ [ :first, :one ].each do |method|
715
+
716
+ describe "##{method}" do
717
+
718
+ let!(:depeche_mode) do
719
+ Band.create(name: "Depeche Mode")
720
+ end
721
+
722
+ let!(:new_order) do
723
+ Band.create(name: "New Order")
724
+ end
725
+
726
+ context "when the context is not cached" do
727
+
728
+ let(:criteria) do
729
+ Band.where(name: "Depeche Mode")
730
+ end
731
+
732
+ let(:context) do
733
+ described_class.new(criteria)
734
+ end
735
+
736
+ it "returns the first matching document" do
737
+ expect(context.send(method)).to eq(depeche_mode)
738
+ end
739
+ end
740
+
741
+ context "when using .desc" do
742
+
743
+ let(:criteria) do
744
+ Band.desc(:name)
745
+ end
746
+
747
+ let(:context) do
748
+ described_class.new(criteria)
749
+ end
750
+
751
+ context "when there is sort on the context" do
752
+
753
+ it "follows the main sort" do
754
+ expect(context.send(method)).to eq(new_order)
755
+ end
756
+ end
757
+
758
+ context "when subsequently calling #last" do
759
+
760
+ it "returns the correnct document" do
761
+ expect(context.send(method)).to eq(new_order)
762
+ expect(context.last).to eq(depeche_mode)
763
+ end
764
+ end
765
+ end
766
+
767
+ context "when using .sort" do
768
+
769
+ let(:criteria) do
770
+ Band.all.sort(:name => -1).criteria
771
+ end
772
+
773
+ let(:context) do
774
+ described_class.new(criteria)
775
+ end
776
+
777
+ context "when there is sort on the context" do
778
+
779
+ it "follows the main sort" do
780
+ expect(context.send(method)).to eq(new_order)
781
+ end
782
+ end
783
+
784
+ context "when subsequently calling #last" do
785
+
786
+ it "returns the correnct document" do
787
+ expect(context.send(method)).to eq(new_order)
788
+ expect(context.last).to eq(depeche_mode)
789
+ end
790
+ end
791
+ end
792
+
793
+ context "when the context is cached" do
794
+
795
+ let(:criteria) do
796
+ Band.where(name: "Depeche Mode").cache
797
+ end
798
+
799
+ let(:context) do
800
+ described_class.new(criteria)
801
+ end
802
+
803
+ context "when the cache is loaded" do
804
+
805
+ before do
806
+ context.to_a
807
+ end
808
+
809
+ it "returns the first document without touching the database" do
810
+ context.should_receive(:query).never
811
+ expect(context.send(method)).to eq(depeche_mode)
812
+ end
813
+ end
814
+
815
+ context "when first method was called before" do
816
+
817
+ before do
818
+ context.first
819
+ end
820
+
821
+ it "returns the first document without touching the database" do
822
+ context.should_receive(:query).never
823
+ context.send(method).should eq(depeche_mode)
824
+ end
825
+ end
826
+ end
827
+ end
828
+ end
829
+
830
+ describe "#initialize" do
831
+
832
+ let(:criteria) do
833
+ Band.where(name: "Depeche Mode").no_timeout
834
+ end
835
+
836
+ let(:context) do
837
+ described_class.new(criteria)
838
+ end
839
+
840
+ it "sets the criteria" do
841
+ expect(context.criteria).to eq(criteria)
842
+ end
843
+
844
+ it "sets the klass" do
845
+ expect(context.klass).to eq(Band)
846
+ end
847
+
848
+ it "sets the query" do
849
+ expect(context.query).to be_a(Moped::Query)
850
+ end
851
+
852
+ it "sets the query selector" do
853
+ expect(context.query.selector).to eq({ "name" => "Depeche Mode" })
854
+ end
855
+
856
+ it "sets timeout options" do
857
+ expect(context.query.operation.flags).to eq([ :no_cursor_timeout ])
858
+ end
859
+ end
860
+
861
+ describe "#last" do
862
+
863
+ context "when no default scope" do
864
+
865
+ let!(:depeche_mode) do
866
+ Band.create(name: "Depeche Mode")
867
+ end
868
+
869
+ let!(:new_order) do
870
+ Band.create(name: "New Order")
871
+ end
872
+
873
+ let(:criteria) do
874
+ Band.all
875
+ end
876
+
877
+ let(:context) do
878
+ described_class.new(criteria)
879
+ end
880
+
881
+ it "returns the last matching document" do
882
+ expect(context.last).to eq(new_order)
883
+ end
884
+ end
885
+
886
+ context "when default scope" do
887
+
888
+ let!(:palm) do
889
+ Tree.create(name: "Palm")
890
+ end
891
+
892
+ let!(:maple) do
893
+ Tree.create(name: "Maple")
894
+ end
895
+
896
+ let(:criteria) do
897
+ Tree.all
898
+ end
899
+
900
+ let(:context) do
901
+ described_class.new(criteria)
902
+ end
903
+
904
+ it "respects default scope" do
905
+ expect(context.last).to eq(palm)
906
+ end
907
+ end
908
+
909
+ context "when subsequently calling #first" do
910
+
911
+ let!(:depeche_mode) do
912
+ Band.create(name: "Depeche Mode")
913
+ end
914
+
915
+ let!(:new_order) do
916
+ Band.create(name: "New Order")
917
+ end
918
+
919
+ let(:criteria) do
920
+ Band.asc(:name)
921
+ end
922
+
923
+ let(:context) do
924
+ described_class.new(criteria)
925
+ end
926
+
927
+ it "returns the correnct document" do
928
+ expect(context.last).to eq(new_order)
929
+ expect(context.first).to eq(depeche_mode)
930
+ end
931
+ end
932
+ end
933
+
934
+ [ :length, :size ].each do |method|
935
+
936
+ describe "##{method}" do
937
+
938
+ before do
939
+ Band.create(name: "Depeche Mode")
940
+ Band.create(name: "New Order")
941
+ end
942
+
943
+ context "when the criteria has a limit" do
944
+
945
+ let(:criteria) do
946
+ Band.limit(1)
947
+ end
948
+
949
+ let(:context) do
950
+ described_class.new(criteria)
951
+ end
952
+
953
+ it "returns the number of documents that match" do
954
+ expect(context.send(method)).to eq(2)
955
+ end
956
+
957
+ context "when calling more than once" do
958
+
959
+ before do
960
+ context.query.should_receive(:count).once.and_return(2)
961
+ end
962
+
963
+ it "returns the cached value for subsequent calls" do
964
+ 2.times { expect(context.send(method)).to eq(2) }
965
+ end
966
+ end
967
+
968
+ context "when the results have been iterated over" do
969
+
970
+ before do
971
+ context.entries
972
+ context.query.should_receive(:count).once.and_return(2)
973
+ end
974
+
975
+ it "returns the cached value for all calls" do
976
+ expect(context.send(method)).to eq(2)
977
+ end
978
+
979
+ context "when the results have been iterated over multiple times" do
980
+
981
+ before do
982
+ context.entries
983
+ end
984
+
985
+ it "resets the length on each full iteration" do
986
+ expect(context).to have(2).items
987
+ end
988
+ end
989
+ end
990
+ end
991
+
992
+ context "when the criteria has no limit" do
993
+
994
+ let(:criteria) do
995
+ Band.where(name: "Depeche Mode")
996
+ end
997
+
998
+ let(:context) do
999
+ described_class.new(criteria)
1000
+ end
1001
+
1002
+ it "returns the number of documents that match" do
1003
+ expect(context.send(method)).to eq(1)
1004
+ end
1005
+
1006
+ context "when calling more than once" do
1007
+
1008
+ before do
1009
+ context.query.should_receive(:count).once.and_return(1)
1010
+ end
1011
+
1012
+ it "returns the cached value for subsequent calls" do
1013
+ 2.times { expect(context.send(method)).to eq(1) }
1014
+ end
1015
+ end
1016
+
1017
+ context "when the results have been iterated over" do
1018
+
1019
+ before do
1020
+ context.entries
1021
+ context.query.should_receive(:count).once.and_return(1)
1022
+ end
1023
+
1024
+ it "returns the cached value for all calls" do
1025
+ expect(context.send(method)).to eq(1)
1026
+ end
1027
+
1028
+ context "when the results have been iterated over multiple times" do
1029
+
1030
+ before do
1031
+ context.entries
1032
+ end
1033
+
1034
+ it "resets the length on each full iteration" do
1035
+ expect(context).to have(1).item
1036
+ end
1037
+ end
1038
+ end
1039
+ end
1040
+ end
1041
+ end
1042
+
1043
+ describe "#limit" do
1044
+
1045
+ let!(:depeche_mode) do
1046
+ Band.create(name: "Depeche Mode")
1047
+ end
1048
+
1049
+ let!(:new_order) do
1050
+ Band.create(name: "New Order")
1051
+ end
1052
+
1053
+ let(:criteria) do
1054
+ Band.all
1055
+ end
1056
+
1057
+ let(:context) do
1058
+ described_class.new(criteria)
1059
+ end
1060
+
1061
+ it "limits the results" do
1062
+ expect(context.limit(1).entries).to eq([ depeche_mode ])
1063
+ end
1064
+ end
1065
+
1066
+ describe "#map" do
1067
+
1068
+ before do
1069
+ Band.create(name: "Depeche Mode")
1070
+ Band.create(name: "New Order")
1071
+ end
1072
+
1073
+ let(:criteria) do
1074
+ Band.all
1075
+ end
1076
+
1077
+ let(:context) do
1078
+ described_class.new(criteria)
1079
+ end
1080
+
1081
+ context "when passed the symbol field name" do
1082
+
1083
+ it "limits query to that field" do
1084
+ criteria.should_receive(:only).with(:name).and_call_original
1085
+ context.map(:name)
1086
+ end
1087
+
1088
+ it "performs mapping" do
1089
+ expect(context.map(:name)).to eq ["Depeche Mode", "New Order"]
1090
+ end
1091
+ end
1092
+
1093
+ context "when passed a block" do
1094
+
1095
+ it "performs mapping" do
1096
+ expect(context.map(&:name)).to eq ["Depeche Mode", "New Order"]
1097
+ end
1098
+ end
1099
+ end
1100
+
1101
+ describe "#map_reduce" do
1102
+
1103
+ let!(:depeche_mode) do
1104
+ Band.create(name: "Depeche Mode", likes: 200)
1105
+ end
1106
+
1107
+ let!(:tool) do
1108
+ Band.create(name: "Tool", likes: 100)
1109
+ end
1110
+
1111
+ let(:map) do
1112
+ %Q{
1113
+ function() {
1114
+ emit(this.name, { likes: this.likes });
1115
+ }}
1116
+ end
1117
+
1118
+ let(:reduce) do
1119
+ %Q{
1120
+ function(key, values) {
1121
+ var result = { likes: 0 };
1122
+ values.forEach(function(value) {
1123
+ result.likes += value.likes;
1124
+ });
1125
+ return result;
1126
+ }}
1127
+ end
1128
+
1129
+ context "when no selection is provided" do
1130
+
1131
+ let(:criteria) do
1132
+ Band.all
1133
+ end
1134
+
1135
+ let(:context) do
1136
+ described_class.new(criteria)
1137
+ end
1138
+
1139
+ let(:results) do
1140
+ context.map_reduce(map, reduce).out(inline: 1)
1141
+ end
1142
+
1143
+ it "returns the first aggregate result" do
1144
+ expect(results).to include(
1145
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1146
+ )
1147
+ end
1148
+
1149
+ it "returns the second aggregate result" do
1150
+ expect(results).to include(
1151
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
1152
+ )
1153
+ end
1154
+
1155
+ it "returns the correct number of documents" do
1156
+ expect(results.count).to eq(2)
1157
+ end
1158
+
1159
+ it "contains the entire raw results" do
1160
+ expect(results["results"]).to eq([
1161
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
1162
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
1163
+ ])
1164
+ end
1165
+
1166
+ it "contains the execution time" do
1167
+ expect(results.time).to_not be_nil
1168
+ end
1169
+
1170
+ it "contains the count statistics" do
1171
+ expect(results["counts"]).to eq({
1172
+ "input" => 2, "emit" => 2, "reduce" => 0, "output" => 2
1173
+ })
1174
+ end
1175
+
1176
+ it "contains the input count" do
1177
+ expect(results.input).to eq(2)
1178
+ end
1179
+
1180
+ it "contains the emitted count" do
1181
+ expect(results.emitted).to eq(2)
1182
+ end
1183
+
1184
+ it "contains the reduced count" do
1185
+ expect(results.reduced).to eq(0)
1186
+ end
1187
+
1188
+ it "contains the output count" do
1189
+ expect(results.output).to eq(2)
1190
+ end
1191
+ end
1192
+
1193
+ context "when selection is provided" do
1194
+
1195
+ let(:criteria) do
1196
+ Band.where(name: "Depeche Mode")
1197
+ end
1198
+
1199
+ let(:context) do
1200
+ described_class.new(criteria)
1201
+ end
1202
+
1203
+ let(:results) do
1204
+ context.map_reduce(map, reduce).out(inline: 1)
1205
+ end
1206
+
1207
+ it "includes the aggregate result" do
1208
+ expect(results).to include(
1209
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1210
+ )
1211
+ end
1212
+
1213
+ it "returns the correct number of documents" do
1214
+ expect(results.count).to eq(1)
1215
+ end
1216
+
1217
+ it "contains the entire raw results" do
1218
+ expect(results["results"]).to eq([
1219
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1220
+ ])
1221
+ end
1222
+
1223
+ it "contains the execution time" do
1224
+ expect(results.time).to_not be_nil
1225
+ end
1226
+
1227
+ it "contains the count statistics" do
1228
+ expect(results["counts"]).to eq({
1229
+ "input" => 1, "emit" => 1, "reduce" => 0, "output" => 1
1230
+ })
1231
+ end
1232
+
1233
+ it "contains the input count" do
1234
+ expect(results.input).to eq(1)
1235
+ end
1236
+
1237
+ it "contains the emitted count" do
1238
+ expect(results.emitted).to eq(1)
1239
+ end
1240
+
1241
+ it "contains the reduced count" do
1242
+ expect(results.reduced).to eq(0)
1243
+ end
1244
+
1245
+ it "contains the output count" do
1246
+ expect(results.output).to eq(1)
1247
+ end
1248
+ end
1249
+
1250
+ context "when sorting is provided" do
1251
+
1252
+ before do
1253
+ Band.index(name: -1)
1254
+ Band.create_indexes
1255
+ end
1256
+
1257
+ let(:criteria) do
1258
+ Band.desc(:name)
1259
+ end
1260
+
1261
+ let(:context) do
1262
+ described_class.new(criteria)
1263
+ end
1264
+
1265
+ let(:results) do
1266
+ context.map_reduce(map, reduce).out(inline: 1)
1267
+ end
1268
+
1269
+ it "returns the first aggregate result" do
1270
+ expect(results).to include(
1271
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
1272
+ )
1273
+ end
1274
+
1275
+ it "returns the second aggregate result" do
1276
+ expect(results).to include(
1277
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1278
+ )
1279
+ end
1280
+
1281
+ it "returns the correct number of documents" do
1282
+ expect(results.count).to eq(2)
1283
+ end
1284
+
1285
+ it "contains the entire raw results" do
1286
+ expect(results["results"]).to eq([
1287
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }},
1288
+ { "_id" => "Tool", "value" => { "likes" => 100 }}
1289
+ ])
1290
+ end
1291
+ end
1292
+
1293
+ context "when limiting is provided" do
1294
+
1295
+ let(:criteria) do
1296
+ Band.limit(1)
1297
+ end
1298
+
1299
+ let(:context) do
1300
+ described_class.new(criteria)
1301
+ end
1302
+
1303
+ let(:results) do
1304
+ context.map_reduce(map, reduce).out(inline: 1)
1305
+ end
1306
+
1307
+ it "returns the first aggregate result" do
1308
+ expect(results).to include(
1309
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1310
+ )
1311
+ end
1312
+
1313
+ it "returns the correct number of documents" do
1314
+ expect(results.count).to eq(1)
1315
+ end
1316
+
1317
+ it "contains the entire raw results" do
1318
+ expect(results["results"]).to eq([
1319
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1320
+ ])
1321
+ end
1322
+ end
1323
+
1324
+ context "when the output is replace" do
1325
+
1326
+ let(:criteria) do
1327
+ Band.limit(1)
1328
+ end
1329
+
1330
+ let(:context) do
1331
+ described_class.new(criteria)
1332
+ end
1333
+
1334
+ let(:results) do
1335
+ context.map_reduce(map, reduce).out(replace: "mr-output")
1336
+ end
1337
+
1338
+ it "returns the correct number of documents" do
1339
+ expect(results.count).to eq(1)
1340
+ end
1341
+
1342
+ it "contains the entire results" do
1343
+ expect(results).to eq([
1344
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1345
+ ])
1346
+ end
1347
+ end
1348
+
1349
+ context "when the output is reduce" do
1350
+
1351
+ let(:criteria) do
1352
+ Band.limit(1)
1353
+ end
1354
+
1355
+ let(:context) do
1356
+ described_class.new(criteria)
1357
+ end
1358
+
1359
+ let(:results) do
1360
+ context.map_reduce(map, reduce).out(reduce: :mr_output)
1361
+ end
1362
+
1363
+ it "returns the correct number of documents" do
1364
+ expect(results.count).to eq(1)
1365
+ end
1366
+
1367
+ it "contains the entire results" do
1368
+ expect(results).to eq([
1369
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1370
+ ])
1371
+ end
1372
+ end
1373
+
1374
+ context "when the output is merge" do
1375
+
1376
+ let(:criteria) do
1377
+ Band.limit(1)
1378
+ end
1379
+
1380
+ let(:context) do
1381
+ described_class.new(criteria)
1382
+ end
1383
+
1384
+ let(:results) do
1385
+ context.map_reduce(map, reduce).out(merge: :mr_output)
1386
+ end
1387
+
1388
+ it "returns the correct number of documents" do
1389
+ expect(results.count).to eq(1)
1390
+ end
1391
+
1392
+ it "contains the entire results" do
1393
+ expect(results).to eq([
1394
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200 }}
1395
+ ])
1396
+ end
1397
+ end
1398
+
1399
+ context "when providing no output" do
1400
+
1401
+ let(:criteria) do
1402
+ Band.limit(1)
1403
+ end
1404
+
1405
+ let(:context) do
1406
+ described_class.new(criteria)
1407
+ end
1408
+
1409
+ let(:results) do
1410
+ context.map_reduce(map, reduce)
1411
+ end
1412
+
1413
+ it "raises an error" do
1414
+ expect {
1415
+ results.entries
1416
+ }.to raise_error(Mongoid::Errors::NoMapReduceOutput)
1417
+ end
1418
+ end
1419
+
1420
+ context "when providing a finalize" do
1421
+
1422
+ let(:criteria) do
1423
+ Band.limit(1)
1424
+ end
1425
+
1426
+ let(:context) do
1427
+ described_class.new(criteria)
1428
+ end
1429
+
1430
+ let(:finalize) do
1431
+ %Q{
1432
+ function(key, value) {
1433
+ value.extra = true;
1434
+ return value;
1435
+ }}
1436
+ end
1437
+
1438
+ let(:results) do
1439
+ context.map_reduce(map, reduce).out(inline: 1).finalize(finalize)
1440
+ end
1441
+
1442
+ it "returns the correct number of documents" do
1443
+ expect(results.count).to eq(1)
1444
+ end
1445
+
1446
+ it "contains the entire results" do
1447
+ expect(results).to eq([
1448
+ { "_id" => "Depeche Mode", "value" => { "likes" => 200, "extra" => true }}
1449
+ ])
1450
+ end
1451
+ end
1452
+ end
1453
+
1454
+ describe "#skip" do
1455
+
1456
+ let!(:depeche_mode) do
1457
+ Band.create(name: "Depeche Mode")
1458
+ end
1459
+
1460
+ let!(:new_order) do
1461
+ Band.create(name: "New Order")
1462
+ end
1463
+
1464
+ let(:criteria) do
1465
+ Band.all
1466
+ end
1467
+
1468
+ let(:context) do
1469
+ described_class.new(criteria)
1470
+ end
1471
+
1472
+ it "limits the results" do
1473
+ expect(context.skip(1).entries).to eq([ new_order ])
1474
+ end
1475
+ end
1476
+
1477
+ describe "#sort" do
1478
+
1479
+ let!(:depeche_mode) do
1480
+ Band.create(name: "Depeche Mode")
1481
+ end
1482
+
1483
+ let!(:new_order) do
1484
+ Band.create(name: "New Order")
1485
+ end
1486
+
1487
+ let(:criteria) do
1488
+ Band.all
1489
+ end
1490
+
1491
+ let(:context) do
1492
+ described_class.new(criteria)
1493
+ end
1494
+
1495
+ context "when providing a spec" do
1496
+
1497
+ it "sorts the results" do
1498
+ expect(context.sort(name: -1).entries).to eq([ new_order, depeche_mode ])
1499
+ end
1500
+
1501
+ it "returns the context" do
1502
+ expect(context.sort(name: 1)).to eq(context)
1503
+ end
1504
+ end
1505
+
1506
+ context "when providing a block" do
1507
+
1508
+ let(:sorted) do
1509
+ context.sort do |a, b|
1510
+ b.name <=> a.name
1511
+ end
1512
+ end
1513
+
1514
+ it "sorts the results in memory" do
1515
+ expect(sorted).to eq([ new_order, depeche_mode ])
1516
+ end
1517
+ end
1518
+ end
1519
+
1520
+ describe "#text_search" do
1521
+
1522
+ let(:criteria) do
1523
+ Word.all
1524
+ end
1525
+
1526
+ let(:context) do
1527
+ described_class.new(criteria)
1528
+ end
1529
+
1530
+ before do
1531
+ Word.with(database: "admin").mongo_session.command(setParameter: 1, textSearchEnabled: true)
1532
+ Word.create_indexes
1533
+ Word.with(safe: true).create!(name: "phase", origin: "latin")
1534
+ end
1535
+
1536
+ after(:all) do
1537
+ Word.remove_indexes
1538
+ end
1539
+
1540
+ context "when the search is projecting" do
1541
+
1542
+ let(:search) do
1543
+ context.text_search("phase").project(name: 1)
1544
+ end
1545
+
1546
+ let(:documents) do
1547
+ search.entries
1548
+ end
1549
+
1550
+ it "limits the fields to the projection" do
1551
+ expect(documents.first.origin).to be_nil
1552
+ end
1553
+ end
1554
+
1555
+ context "when the search is not projecting" do
1556
+
1557
+ let(:search) do
1558
+ context.text_search("phase")
1559
+ end
1560
+
1561
+ let(:documents) do
1562
+ search.entries
1563
+ end
1564
+
1565
+ it "returns all fields" do
1566
+ expect(documents.first.origin).to eq("latin")
1567
+ end
1568
+ end
1569
+ end
1570
+
1571
+ describe "#update" do
1572
+
1573
+ let!(:depeche_mode) do
1574
+ Band.create(name: "Depeche Mode")
1575
+ end
1576
+
1577
+ let!(:new_order) do
1578
+ Band.create(name: "New Order")
1579
+ end
1580
+
1581
+ let(:criteria) do
1582
+ Band.all
1583
+ end
1584
+
1585
+ let(:context) do
1586
+ described_class.new(criteria)
1587
+ end
1588
+
1589
+ context "when providing attributes" do
1590
+
1591
+ context "when the attributes are of the correct type" do
1592
+
1593
+ before do
1594
+ context.update(name: "Smiths")
1595
+ end
1596
+
1597
+ it "updates only the first matching document" do
1598
+ expect(depeche_mode.reload.name).to eq("Smiths")
1599
+ end
1600
+
1601
+ it "does not update the last matching document" do
1602
+ expect(new_order.reload.name).to eq("New Order")
1603
+ end
1604
+ end
1605
+
1606
+ context "when the attributes must be mongoized" do
1607
+
1608
+ context "when coercing a string to integer" do
1609
+
1610
+ before do
1611
+ context.update(member_count: "1")
1612
+ end
1613
+
1614
+ it "updates the first matching document" do
1615
+ expect(depeche_mode.reload.member_count).to eq(1)
1616
+ end
1617
+
1618
+ it "does not update the last matching document" do
1619
+ expect(new_order.reload.member_count).to be_nil
1620
+ end
1621
+ end
1622
+
1623
+ context "when coercing a string to date" do
1624
+
1625
+ before do
1626
+ context.update(founded: "1979/1/1")
1627
+ end
1628
+
1629
+ it "updates the first matching document" do
1630
+ expect(depeche_mode.reload.founded).to eq(Date.new(1979, 1, 1))
1631
+ end
1632
+
1633
+ it "does not update the last matching document" do
1634
+ expect(new_order.reload.founded).to be_nil
1635
+ end
1636
+ end
1637
+ end
1638
+ end
1639
+
1640
+ context "when providing atomic operations" do
1641
+
1642
+ context "when only atomic operations are provided" do
1643
+
1644
+ context "when the attributes are in the correct type" do
1645
+
1646
+ before do
1647
+ context.update("$set" => { name: "Smiths" })
1648
+ end
1649
+
1650
+ it "updates the first matching document" do
1651
+ expect(depeche_mode.reload.name).to eq("Smiths")
1652
+ end
1653
+
1654
+ it "does not update the last matching document" do
1655
+ expect(new_order.reload.name).to eq("New Order")
1656
+ end
1657
+ end
1658
+
1659
+ context "when the attributes must be mongoized" do
1660
+
1661
+ before do
1662
+ context.update("$set" => { member_count: "1" })
1663
+ end
1664
+
1665
+ it "updates the first matching document" do
1666
+ expect(depeche_mode.reload.member_count).to eq(1)
1667
+ end
1668
+
1669
+ it "does not update the last matching document" do
1670
+ expect(new_order.reload.member_count).to be_nil
1671
+ end
1672
+ end
1673
+ end
1674
+
1675
+ context "when a mix are provided" do
1676
+
1677
+ before do
1678
+ context.update("$set" => { name: "Smiths" }, likes: 100)
1679
+ end
1680
+
1681
+ it "updates the first matching document's set" do
1682
+ expect(depeche_mode.reload.name).to eq("Smiths")
1683
+ end
1684
+
1685
+ it "updates the first matching document's updates" do
1686
+ expect(depeche_mode.reload.likes).to eq(100)
1687
+ end
1688
+
1689
+ it "does not update the last matching document's set" do
1690
+ expect(new_order.reload.name).to eq("New Order")
1691
+ end
1692
+
1693
+ it "does not update the last matching document's updates" do
1694
+ expect(new_order.reload.likes).to be_nil
1695
+ end
1696
+ end
1697
+ end
1698
+
1699
+ context "when providing no attributes" do
1700
+
1701
+ it "returns false" do
1702
+ expect(context.update).to be_false
1703
+ end
1704
+ end
1705
+ end
1706
+
1707
+ describe "#update_all" do
1708
+
1709
+ let!(:depeche_mode) do
1710
+ Band.create(name: "Depeche Mode", origin: "Essex")
1711
+ end
1712
+
1713
+ let!(:new_order) do
1714
+ Band.create(name: "New Order")
1715
+ end
1716
+
1717
+ let(:criteria) do
1718
+ Band.all
1719
+ end
1720
+
1721
+ let(:context) do
1722
+ described_class.new(criteria)
1723
+ end
1724
+
1725
+ context "when providing attributes" do
1726
+
1727
+ context "when the attributes are of the correct type" do
1728
+
1729
+ before do
1730
+ context.update_all(name: "Smiths")
1731
+ end
1732
+
1733
+ it "updates the first matching document" do
1734
+ expect(depeche_mode.reload.name).to eq("Smiths")
1735
+ end
1736
+
1737
+ it "does not clear out other attributes" do
1738
+ expect(depeche_mode.reload.origin).to eq("Essex")
1739
+ end
1740
+
1741
+ it "updates the last matching document" do
1742
+ expect(new_order.reload.name).to eq("Smiths")
1743
+ end
1744
+ end
1745
+
1746
+ context "when the attributes must be mongoized" do
1747
+
1748
+ before do
1749
+ context.update_all(member_count: "1")
1750
+ end
1751
+
1752
+ it "updates the first matching document" do
1753
+ expect(depeche_mode.reload.member_count).to eq(1)
1754
+ end
1755
+
1756
+ it "updates the last matching document" do
1757
+ expect(new_order.reload.member_count).to eq(1)
1758
+ end
1759
+ end
1760
+
1761
+ context "when using aliased field names" do
1762
+
1763
+ before do
1764
+ context.update_all(years: 100)
1765
+ end
1766
+
1767
+ it "updates the first matching document" do
1768
+ expect(depeche_mode.reload.years).to eq(100)
1769
+ end
1770
+
1771
+ it "updates the last matching document" do
1772
+ expect(new_order.reload.years).to eq(100)
1773
+ end
1774
+ end
1775
+ end
1776
+
1777
+ context "when providing atomic operations" do
1778
+
1779
+ context "when only atomic operations are provided" do
1780
+
1781
+ context "when the attributes are in the correct type" do
1782
+
1783
+ before do
1784
+ context.update_all("$set" => { name: "Smiths" })
1785
+ end
1786
+
1787
+ it "updates the first matching document" do
1788
+ expect(depeche_mode.reload.name).to eq("Smiths")
1789
+ end
1790
+
1791
+ it "updates the last matching document" do
1792
+ expect(new_order.reload.name).to eq("Smiths")
1793
+ end
1794
+ end
1795
+
1796
+ context "when the attributes must be mongoized" do
1797
+
1798
+ before do
1799
+ context.update_all("$set" => { member_count: "1" })
1800
+ end
1801
+
1802
+ it "updates the first matching document" do
1803
+ expect(depeche_mode.reload.member_count).to eq(1)
1804
+ end
1805
+
1806
+ it "updates the last matching document" do
1807
+ expect(new_order.reload.member_count).to eq(1)
1808
+ end
1809
+ end
1810
+ end
1811
+
1812
+ context "when a mix are provided" do
1813
+
1814
+ before do
1815
+ context.update_all("$set" => { name: "Smiths" }, likes: 100)
1816
+ end
1817
+
1818
+ it "updates the first matching document's set" do
1819
+ expect(depeche_mode.reload.name).to eq("Smiths")
1820
+ end
1821
+
1822
+ it "updates the first matching document's updates" do
1823
+ expect(depeche_mode.reload.likes).to eq(100)
1824
+ end
1825
+
1826
+ it "updates the last matching document's set" do
1827
+ expect(new_order.reload.name).to eq("Smiths")
1828
+ end
1829
+
1830
+ it "updates the last matching document's updates" do
1831
+ expect(new_order.reload.likes).to eq(100)
1832
+ end
1833
+ end
1834
+ end
1835
+
1836
+ context "when providing no attributes" do
1837
+
1838
+ it "returns false" do
1839
+ expect(context.update_all).to be_false
1840
+ end
1841
+ end
1842
+ end
1843
+ end