mongoid 3.1.6 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (571) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +479 -8
  3. data/README.md +10 -7
  4. data/lib/config/locales/en.yml +34 -20
  5. data/lib/mongoid.rb +10 -76
  6. data/lib/mongoid/atomic.rb +3 -14
  7. data/lib/mongoid/atomic/paths/embedded.rb +0 -30
  8. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  9. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  10. data/lib/mongoid/atomic/paths/root.rb +0 -13
  11. data/lib/mongoid/attributes.rb +65 -101
  12. data/lib/mongoid/attributes/dynamic.rb +154 -0
  13. data/lib/mongoid/attributes/nested.rb +82 -0
  14. data/lib/mongoid/attributes/processing.rb +13 -66
  15. data/lib/mongoid/{dirty.rb → changeable.rb} +32 -2
  16. data/lib/mongoid/composable.rb +105 -0
  17. data/lib/mongoid/config.rb +3 -9
  18. data/lib/mongoid/config/options.rb +1 -1
  19. data/lib/mongoid/contextual.rb +2 -0
  20. data/lib/mongoid/contextual/aggregable/memory.rb +2 -2
  21. data/lib/mongoid/contextual/aggregable/mongo.rb +7 -9
  22. data/lib/mongoid/contextual/atomic.rb +53 -53
  23. data/lib/mongoid/contextual/geo_near.rb +1 -1
  24. data/lib/mongoid/contextual/map_reduce.rb +4 -2
  25. data/lib/mongoid/contextual/memory.rb +23 -11
  26. data/lib/mongoid/contextual/mongo.rb +75 -57
  27. data/lib/mongoid/contextual/none.rb +90 -0
  28. data/lib/mongoid/contextual/text_search.rb +178 -0
  29. data/lib/mongoid/copyable.rb +2 -3
  30. data/lib/mongoid/criteria.rb +39 -34
  31. data/lib/mongoid/criteria/#findable.rb# +141 -0
  32. data/lib/mongoid/{criterion → criteria}/findable.rb +7 -47
  33. data/lib/mongoid/{criterion/inspection.rb → criteria/inspectable.rb} +2 -2
  34. data/lib/mongoid/{criterion → criteria}/marshalable.rb +3 -1
  35. data/lib/mongoid/{criterion → criteria}/modifiable.rb +28 -8
  36. data/lib/mongoid/criteria/permission.rb +70 -0
  37. data/lib/mongoid/{criterion/scoping.rb → criteria/scopable.rb} +2 -2
  38. data/lib/mongoid/document.rb +39 -24
  39. data/lib/mongoid/errors.rb +4 -1
  40. data/lib/mongoid/errors/document_not_destroyed.rb +25 -0
  41. data/lib/mongoid/errors/document_not_found.rb +2 -1
  42. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  43. data/lib/mongoid/errors/invalid_storage_parent.rb +26 -0
  44. data/lib/mongoid/errors/invalid_value.rb +16 -0
  45. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  46. data/lib/mongoid/errors/readonly_document.rb +24 -0
  47. data/lib/mongoid/extensions.rb +15 -7
  48. data/lib/mongoid/extensions/array.rb +3 -3
  49. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  50. data/lib/mongoid/extensions/boolean.rb +15 -17
  51. data/lib/mongoid/extensions/date.rb +1 -1
  52. data/lib/mongoid/extensions/date_time.rb +3 -3
  53. data/lib/mongoid/extensions/float.rb +2 -1
  54. data/lib/mongoid/extensions/hash.rb +3 -3
  55. data/lib/mongoid/extensions/integer.rb +1 -1
  56. data/lib/mongoid/extensions/object.rb +7 -7
  57. data/lib/mongoid/extensions/object_id.rb +5 -5
  58. data/lib/mongoid/extensions/range.rb +9 -3
  59. data/lib/mongoid/extensions/regexp.rb +1 -1
  60. data/lib/mongoid/extensions/set.rb +1 -1
  61. data/lib/mongoid/extensions/string.rb +6 -18
  62. data/lib/mongoid/extensions/symbol.rb +1 -1
  63. data/lib/mongoid/extensions/time.rb +3 -3
  64. data/lib/mongoid/extensions/time_with_zone.rb +1 -1
  65. data/lib/mongoid/factory.rb +8 -6
  66. data/lib/mongoid/fields.rb +41 -8
  67. data/lib/mongoid/fields/foreign_key.rb +3 -3
  68. data/lib/mongoid/fields/localized.rb +1 -1
  69. data/lib/mongoid/fields/standard.rb +5 -17
  70. data/lib/mongoid/fields/validators/macro.rb +15 -5
  71. data/lib/mongoid/{finders.rb → findable.rb} +35 -7
  72. data/lib/mongoid/{indexes.rb → indexable.rb} +50 -55
  73. data/lib/mongoid/indexable/specification.rb +104 -0
  74. data/lib/mongoid/{indexes → indexable}/validators/options.rb +2 -1
  75. data/lib/mongoid/{inspection.rb → inspectable.rb} +15 -11
  76. data/lib/mongoid/{callbacks.rb → interceptable.rb} +30 -62
  77. data/lib/mongoid/log_subscriber.rb +55 -0
  78. data/lib/mongoid/matchable.rb +152 -0
  79. data/lib/mongoid/{matchers → matchable}/all.rb +1 -1
  80. data/lib/mongoid/{matchers → matchable}/and.rb +2 -2
  81. data/lib/mongoid/{matchers → matchable}/default.rb +1 -1
  82. data/lib/mongoid/{matchers → matchable}/exists.rb +1 -1
  83. data/lib/mongoid/{matchers → matchable}/gt.rb +1 -1
  84. data/lib/mongoid/{matchers → matchable}/gte.rb +1 -1
  85. data/lib/mongoid/{matchers → matchable}/in.rb +2 -2
  86. data/lib/mongoid/{matchers → matchable}/lt.rb +1 -1
  87. data/lib/mongoid/{matchers → matchable}/lte.rb +1 -1
  88. data/lib/mongoid/{matchers → matchable}/ne.rb +2 -2
  89. data/lib/mongoid/{matchers → matchable}/nin.rb +3 -2
  90. data/lib/mongoid/{matchers → matchable}/or.rb +2 -2
  91. data/lib/mongoid/{matchers → matchable}/size.rb +1 -1
  92. data/lib/mongoid/persistable.rb +216 -0
  93. data/lib/mongoid/persistable/creatable.rb +189 -0
  94. data/lib/mongoid/persistable/deletable.rb +149 -0
  95. data/lib/mongoid/persistable/destroyable.rb +60 -0
  96. data/lib/mongoid/persistable/incrementable.rb +36 -0
  97. data/lib/mongoid/persistable/logical.rb +38 -0
  98. data/lib/mongoid/persistable/poppable.rb +39 -0
  99. data/lib/mongoid/persistable/pullable.rb +55 -0
  100. data/lib/mongoid/persistable/pushable.rb +62 -0
  101. data/lib/mongoid/persistable/renamable.rb +35 -0
  102. data/lib/mongoid/persistable/savable.rb +52 -0
  103. data/lib/mongoid/persistable/settable.rb +33 -0
  104. data/lib/mongoid/persistable/unsettable.rb +36 -0
  105. data/lib/mongoid/persistable/updatable.rb +153 -0
  106. data/lib/mongoid/persistable/upsertable.rb +55 -0
  107. data/lib/mongoid/positional.rb +71 -0
  108. data/lib/mongoid/query_cache.rb +255 -0
  109. data/lib/mongoid/railtie.rb +34 -60
  110. data/lib/mongoid/railties/database.rake +9 -25
  111. data/lib/mongoid/relations.rb +11 -25
  112. data/lib/mongoid/relations/accessors.rb +15 -51
  113. data/lib/mongoid/relations/auto_save.rb +15 -36
  114. data/lib/mongoid/relations/binding.rb +2 -25
  115. data/lib/mongoid/relations/bindings/embedded/in.rb +1 -1
  116. data/lib/mongoid/relations/bindings/embedded/many.rb +1 -3
  117. data/lib/mongoid/relations/bindings/referenced/in.rb +3 -8
  118. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -2
  119. data/lib/mongoid/relations/builder.rb +1 -1
  120. data/lib/mongoid/relations/builders.rb +2 -2
  121. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  122. data/lib/mongoid/relations/builders/nested_attributes/many.rb +10 -13
  123. data/lib/mongoid/relations/builders/nested_attributes/one.rb +5 -6
  124. data/lib/mongoid/relations/builders/referenced/in.rb +1 -1
  125. data/lib/mongoid/relations/builders/referenced/many.rb +1 -2
  126. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +1 -2
  127. data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
  128. data/lib/mongoid/relations/cascading.rb +3 -5
  129. data/lib/mongoid/relations/constraint.rb +1 -1
  130. data/lib/mongoid/relations/conversions.rb +1 -1
  131. data/lib/mongoid/relations/counter_cache.rb +39 -15
  132. data/lib/mongoid/relations/eager.rb +46 -0
  133. data/lib/mongoid/relations/eager/base.rb +149 -0
  134. data/lib/mongoid/relations/eager/belongs_to.rb +31 -0
  135. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +47 -0
  136. data/lib/mongoid/relations/eager/has_many.rb +38 -0
  137. data/lib/mongoid/relations/eager/has_one.rb +30 -0
  138. data/lib/mongoid/relations/embedded/batchable.rb +4 -5
  139. data/lib/mongoid/relations/embedded/in.rb +4 -4
  140. data/lib/mongoid/relations/embedded/many.rb +14 -32
  141. data/lib/mongoid/relations/embedded/one.rb +1 -1
  142. data/lib/mongoid/relations/macros.rb +3 -4
  143. data/lib/mongoid/relations/many.rb +51 -31
  144. data/lib/mongoid/relations/marshalable.rb +3 -3
  145. data/lib/mongoid/relations/metadata.rb +14 -79
  146. data/lib/mongoid/relations/nested_builder.rb +2 -2
  147. data/lib/mongoid/relations/one.rb +1 -1
  148. data/lib/mongoid/relations/options.rb +1 -0
  149. data/lib/mongoid/relations/polymorphic.rb +0 -1
  150. data/lib/mongoid/relations/proxy.rb +21 -41
  151. data/lib/mongoid/relations/referenced/in.rb +4 -20
  152. data/lib/mongoid/relations/referenced/many.rb +22 -35
  153. data/lib/mongoid/relations/referenced/many_to_many.rb +19 -42
  154. data/lib/mongoid/relations/referenced/one.rb +6 -25
  155. data/lib/mongoid/relations/synchronization.rb +4 -4
  156. data/lib/mongoid/relations/targets/enumerable.rb +10 -10
  157. data/lib/mongoid/relations/touchable.rb +34 -1
  158. data/lib/mongoid/{reloading.rb → reloadable.rb} +7 -5
  159. data/lib/mongoid/{scoping.rb → scopable.rb} +36 -36
  160. data/lib/mongoid/selectable.rb +59 -0
  161. data/lib/mongoid/{serialization.rb → serializable.rb} +11 -2
  162. data/lib/mongoid/sessions.rb +37 -345
  163. data/lib/mongoid/sessions/factory.rb +2 -0
  164. data/lib/mongoid/sessions/options.rb +185 -0
  165. data/lib/mongoid/sessions/storage_options.rb +140 -0
  166. data/lib/mongoid/sessions/thread_options.rb +19 -0
  167. data/lib/mongoid/sessions/validators/storage.rb +16 -3
  168. data/lib/mongoid/{sharding.rb → shardable.rb} +5 -1
  169. data/lib/mongoid/{state.rb → stateful.rb} +13 -1
  170. data/lib/mongoid/support/query_counter.rb +23 -0
  171. data/lib/mongoid/tasks/database.rake +31 -0
  172. data/lib/mongoid/tasks/database.rb +107 -0
  173. data/lib/mongoid/threaded.rb +26 -172
  174. data/lib/mongoid/threaded/lifecycle.rb +0 -28
  175. data/lib/mongoid/timestamps/updated/short.rb +2 -2
  176. data/lib/mongoid/{hierarchy.rb → traversable.rb} +15 -7
  177. data/lib/mongoid/{validations.rb → validatable.rb} +23 -10
  178. data/lib/mongoid/{validations → validatable}/associated.rb +4 -2
  179. data/lib/mongoid/{validations → validatable}/format.rb +1 -1
  180. data/lib/mongoid/{validations → validatable}/length.rb +1 -1
  181. data/lib/mongoid/{validations → validatable}/localizable.rb +1 -1
  182. data/lib/mongoid/{validations → validatable}/macros.rb +4 -3
  183. data/lib/mongoid/{validations → validatable}/presence.rb +1 -1
  184. data/lib/mongoid/{validations → validatable}/queryable.rb +1 -2
  185. data/lib/mongoid/{validations → validatable}/uniqueness.rb +25 -21
  186. data/lib/mongoid/version.rb +1 -1
  187. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +46 -25
  188. data/lib/rails/generators/mongoid/model/model_generator.rb +0 -1
  189. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +0 -3
  190. data/lib/rails/generators/mongoid_generator.rb +3 -40
  191. data/lib/rails/mongoid.rb +0 -122
  192. data/lib/support/ruby_version.rb +1 -1
  193. data/spec/app/models/account.rb +2 -6
  194. data/spec/app/models/acolyte.rb +2 -1
  195. data/spec/app/models/actor.rb +0 -1
  196. data/spec/app/models/address.rb +8 -3
  197. data/spec/app/models/animal.rb +1 -1
  198. data/spec/app/models/appointment.rb +3 -3
  199. data/spec/app/models/article.rb +1 -4
  200. data/spec/app/models/audio.rb +5 -0
  201. data/spec/app/models/author.rb +0 -2
  202. data/spec/app/models/band.rb +3 -2
  203. data/spec/app/models/bar.rb +1 -0
  204. data/spec/app/models/book.rb +1 -0
  205. data/spec/app/models/building.rb +0 -2
  206. data/spec/app/models/building_address.rb +0 -2
  207. data/spec/app/models/bus.rb +1 -1
  208. data/spec/app/models/canvas.rb +1 -1
  209. data/spec/app/models/contextable_item.rb +5 -0
  210. data/spec/app/models/contractor.rb +0 -2
  211. data/spec/app/models/country_code.rb +1 -1
  212. data/spec/app/models/definition.rb +2 -2
  213. data/spec/app/models/dog.rb +1 -1
  214. data/spec/app/models/draft.rb +9 -0
  215. data/spec/app/models/dragon.rb +4 -0
  216. data/spec/app/models/drug.rb +1 -3
  217. data/spec/app/models/dungeon.rb +4 -0
  218. data/spec/app/models/edit.rb +5 -0
  219. data/spec/app/models/even.rb +7 -0
  220. data/spec/app/models/event.rb +1 -1
  221. data/spec/app/models/filesystem.rb +1 -0
  222. data/spec/app/models/fish.rb +0 -1
  223. data/spec/app/models/fruits.rb +6 -0
  224. data/spec/app/models/game.rb +0 -2
  225. data/spec/app/models/house.rb +1 -3
  226. data/spec/app/models/id_key.rb +6 -0
  227. data/spec/app/models/item.rb +1 -5
  228. data/spec/app/models/jar.rb +1 -1
  229. data/spec/app/models/label.rb +4 -4
  230. data/spec/app/models/line_item.rb +1 -1
  231. data/spec/app/models/login.rb +1 -1
  232. data/spec/app/models/message.rb +8 -0
  233. data/spec/app/models/movie.rb +1 -0
  234. data/spec/app/models/name.rb +3 -3
  235. data/spec/app/models/note.rb +3 -1
  236. data/spec/app/models/odd.rb +7 -0
  237. data/spec/app/models/oscar.rb +1 -1
  238. data/spec/app/models/parent_doc.rb +1 -1
  239. data/spec/app/models/person.rb +16 -10
  240. data/spec/app/models/phone.rb +1 -3
  241. data/spec/app/models/player.rb +3 -3
  242. data/spec/app/models/post.rb +5 -3
  243. data/spec/app/models/preference.rb +1 -1
  244. data/spec/app/models/quiz.rb +0 -3
  245. data/spec/app/models/record.rb +10 -5
  246. data/spec/app/models/registry.rb +1 -1
  247. data/spec/app/models/server.rb +1 -1
  248. data/spec/app/models/service.rb +3 -3
  249. data/spec/app/models/sound.rb +5 -0
  250. data/spec/app/models/symptom.rb +1 -1
  251. data/spec/app/models/template.rb +1 -1
  252. data/spec/app/models/title.rb +0 -1
  253. data/spec/app/models/track.rb +5 -5
  254. data/spec/app/models/tree.rb +3 -3
  255. data/spec/app/models/video.rb +1 -5
  256. data/spec/app/models/wiki_page.rb +2 -5
  257. data/spec/app/models/word.rb +3 -0
  258. data/spec/app/models/word_origin.rb +1 -1
  259. data/spec/config/mongoid.yml +7 -8
  260. data/spec/helpers.rb +18 -0
  261. data/spec/mongoid/#atomic_spec.rb# +365 -0
  262. data/spec/mongoid/atomic/modifiers_spec.rb +22 -22
  263. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +8 -49
  264. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +7 -49
  265. data/spec/mongoid/atomic/paths/root_spec.rb +3 -61
  266. data/spec/mongoid/atomic/paths_spec.rb +19 -19
  267. data/spec/mongoid/atomic_spec.rb +19 -19
  268. data/spec/mongoid/{nested_attributes_spec.rb → attributes/nested_spec.rb} +474 -592
  269. data/spec/mongoid/attributes/readonly_spec.rb +58 -18
  270. data/spec/mongoid/attributes_spec.rb +349 -434
  271. data/spec/mongoid/{dirty_spec.rb → changeable_spec.rb} +203 -153
  272. data/spec/mongoid/{components_spec.rb → composable_spec.rb} +3 -3
  273. data/spec/mongoid/config/environment_spec.rb +3 -3
  274. data/spec/mongoid/config/options_spec.rb +6 -6
  275. data/spec/mongoid/config_spec.rb +24 -48
  276. data/spec/mongoid/contextual/aggregable/memory_spec.rb +12 -12
  277. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +78 -38
  278. data/spec/mongoid/contextual/atomic_spec.rb +60 -56
  279. data/spec/mongoid/contextual/find_and_modify_spec.rb +14 -14
  280. data/spec/mongoid/contextual/geo_near_spec.rb +22 -22
  281. data/spec/mongoid/contextual/map_reduce_spec.rb +27 -27
  282. data/spec/mongoid/contextual/memory_spec.rb +156 -94
  283. data/spec/mongoid/contextual/mongo_spec.rb +238 -150
  284. data/spec/mongoid/contextual/none_spec.rb +127 -0
  285. data/spec/mongoid/contextual/text_search_spec.rb +209 -0
  286. data/spec/mongoid/copyable_spec.rb +56 -68
  287. data/spec/mongoid/criteria/findable_spec.rb +991 -0
  288. data/spec/mongoid/{criterion/inspection_spec.rb → criteria/inspectable_spec.rb} +5 -5
  289. data/spec/mongoid/{criterion → criteria}/marshalable_spec.rb +2 -2
  290. data/spec/mongoid/criteria/modifiable_spec.rb +1252 -0
  291. data/spec/mongoid/{criterion/scoping_spec.rb → criteria/scopable_spec.rb} +37 -37
  292. data/spec/mongoid/criteria_spec.rb +715 -2421
  293. data/spec/mongoid/document_spec.rb +171 -121
  294. data/spec/mongoid/equality_spec.rb +22 -22
  295. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +3 -3
  296. data/spec/mongoid/errors/callback_spec.rb +3 -3
  297. data/spec/mongoid/errors/delete_restriction_spec.rb +3 -3
  298. data/spec/mongoid/errors/document_not_destroyed_spec.rb +33 -0
  299. data/spec/mongoid/errors/document_not_found_spec.rb +11 -11
  300. data/spec/mongoid/errors/eager_load_spec.rb +3 -3
  301. data/spec/mongoid/errors/invalid_collection_spec.rb +3 -3
  302. data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -3
  303. data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -3
  304. data/spec/mongoid/errors/invalid_field_spec.rb +3 -3
  305. data/spec/mongoid/errors/invalid_find_spec.rb +3 -3
  306. data/spec/mongoid/errors/invalid_includes_spec.rb +3 -3
  307. data/spec/mongoid/errors/invalid_index_spec.rb +3 -3
  308. data/spec/mongoid/errors/invalid_options_spec.rb +3 -3
  309. data/spec/mongoid/errors/invalid_path_spec.rb +3 -3
  310. data/spec/mongoid/errors/invalid_scope_spec.rb +5 -5
  311. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -3
  312. data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -3
  313. data/spec/mongoid/errors/invalid_time_spec.rb +3 -3
  314. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -3
  315. data/spec/mongoid/errors/mixed_relations_spec.rb +3 -3
  316. data/spec/mongoid/errors/mixed_session_configuration_spec.rb +3 -3
  317. data/spec/mongoid/errors/mongoid_error_spec.rb +8 -8
  318. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +3 -3
  319. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  320. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -3
  321. data/spec/mongoid/errors/no_metadata_spec.rb +3 -3
  322. data/spec/mongoid/errors/no_parent_spec.rb +3 -3
  323. data/spec/mongoid/errors/no_session_config_spec.rb +3 -3
  324. data/spec/mongoid/errors/no_session_database_spec.rb +3 -3
  325. data/spec/mongoid/errors/no_session_hosts_spec.rb +3 -3
  326. data/spec/mongoid/errors/no_sessions_config_spec.rb +3 -3
  327. data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -3
  328. data/spec/mongoid/errors/readonly_document_spec.rb +29 -0
  329. data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -3
  330. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -3
  331. data/spec/mongoid/errors/unknown_attribute_spec.rb +5 -5
  332. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -3
  333. data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -3
  334. data/spec/mongoid/errors/validations_spec.rb +7 -7
  335. data/spec/mongoid/extensions/array_spec.rb +61 -61
  336. data/spec/mongoid/extensions/big_decimal_spec.rb +11 -11
  337. data/spec/mongoid/extensions/binary_spec.rb +12 -12
  338. data/spec/mongoid/extensions/boolean_spec.rb +18 -18
  339. data/spec/mongoid/extensions/date_spec.rb +13 -13
  340. data/spec/mongoid/extensions/date_time_spec.rb +8 -8
  341. data/spec/mongoid/extensions/false_class_spec.rb +5 -5
  342. data/spec/mongoid/extensions/float_spec.rb +29 -15
  343. data/spec/mongoid/extensions/hash_spec.rb +29 -29
  344. data/spec/mongoid/extensions/integer_spec.rb +15 -15
  345. data/spec/mongoid/extensions/module_spec.rb +2 -2
  346. data/spec/mongoid/extensions/nil_class_spec.rb +1 -1
  347. data/spec/mongoid/extensions/object_id_spec.rb +134 -134
  348. data/spec/mongoid/extensions/object_spec.rb +26 -26
  349. data/spec/mongoid/extensions/range_spec.rb +61 -12
  350. data/spec/mongoid/extensions/regexp_spec.rb +4 -4
  351. data/spec/mongoid/extensions/set_spec.rb +4 -4
  352. data/spec/mongoid/extensions/string_spec.rb +35 -46
  353. data/spec/mongoid/extensions/symbol_spec.rb +9 -9
  354. data/spec/mongoid/extensions/time_spec.rb +49 -49
  355. data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -34
  356. data/spec/mongoid/extensions/true_class_spec.rb +5 -5
  357. data/spec/mongoid/extensions_spec.rb +29 -0
  358. data/spec/mongoid/factory_spec.rb +15 -15
  359. data/spec/mongoid/fields/foreign_key_spec.rb +73 -66
  360. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +15 -15
  361. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +22 -22
  362. data/spec/mongoid/fields/localized_spec.rb +38 -23
  363. data/spec/mongoid/fields/standard_spec.rb +12 -12
  364. data/spec/mongoid/fields_spec.rb +263 -217
  365. data/spec/mongoid/findable_spec.rb +509 -0
  366. data/spec/mongoid/indexable/specification_spec.rb +102 -0
  367. data/spec/mongoid/{indexes_spec.rb → indexable_spec.rb} +171 -51
  368. data/spec/mongoid/{inspection_spec.rb → inspectable_spec.rb} +6 -14
  369. data/spec/mongoid/{callbacks_spec.rb → interceptable_spec.rb} +117 -116
  370. data/spec/mongoid/log_subscriber_spec.rb +75 -0
  371. data/spec/mongoid/loggable_spec.rb +1 -1
  372. data/spec/mongoid/{matchers → matchable}/all_spec.rb +4 -4
  373. data/spec/mongoid/{matchers → matchable}/and_spec.rb +11 -11
  374. data/spec/mongoid/{matchers → matchable}/default_spec.rb +15 -15
  375. data/spec/mongoid/{matchers → matchable}/exists_spec.rb +5 -5
  376. data/spec/mongoid/{matchers → matchable}/gt_spec.rb +9 -8
  377. data/spec/mongoid/{matchers → matchable}/gte_spec.rb +7 -7
  378. data/spec/mongoid/matchable/in_spec.rb +49 -0
  379. data/spec/mongoid/{matchers → matchable}/lt_spec.rb +7 -7
  380. data/spec/mongoid/{matchers → matchable}/lte_spec.rb +7 -7
  381. data/spec/mongoid/matchable/ne_spec.rb +46 -0
  382. data/spec/mongoid/matchable/nin_spec.rb +48 -0
  383. data/spec/mongoid/{matchers → matchable}/or_spec.rb +6 -6
  384. data/spec/mongoid/{matchers → matchable}/size_spec.rb +3 -3
  385. data/spec/mongoid/{matchers_spec.rb → matchable_spec.rb} +41 -41
  386. data/spec/mongoid/persistable/creatable_spec.rb +553 -0
  387. data/spec/mongoid/persistable/deletable_spec.rb +218 -0
  388. data/spec/mongoid/persistable/destroyable_spec.rb +192 -0
  389. data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
  390. data/spec/mongoid/persistable/logical_spec.rb +143 -0
  391. data/spec/mongoid/persistable/poppable_spec.rb +115 -0
  392. data/spec/mongoid/persistable/pullable_spec.rb +228 -0
  393. data/spec/mongoid/persistable/pushable_spec.rb +258 -0
  394. data/spec/mongoid/persistable/renamable_spec.rb +135 -0
  395. data/spec/mongoid/persistable/savable_spec.rb +498 -0
  396. data/spec/mongoid/persistable/settable_spec.rb +162 -0
  397. data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
  398. data/spec/mongoid/persistable/updatable_spec.rb +558 -0
  399. data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
  400. data/spec/mongoid/persistable_spec.rb +206 -0
  401. data/spec/mongoid/{atomic/positionable_spec.rb → positional_spec.rb} +14 -19
  402. data/spec/mongoid/query_cache_spec.rb +263 -0
  403. data/spec/mongoid/railties/document_spec.rb +2 -2
  404. data/spec/mongoid/relations/accessors_spec.rb +53 -145
  405. data/spec/mongoid/relations/auto_save_spec.rb +37 -17
  406. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +12 -12
  407. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +3 -3
  408. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +5 -5
  409. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +26 -26
  410. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +10 -10
  411. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +19 -19
  412. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +12 -12
  413. data/spec/mongoid/relations/builders/embedded/in_spec.rb +4 -4
  414. data/spec/mongoid/relations/builders/embedded/many_spec.rb +18 -18
  415. data/spec/mongoid/relations/builders/embedded/one_spec.rb +11 -11
  416. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +12 -13
  417. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +14 -14
  418. data/spec/mongoid/relations/builders/referenced/in_spec.rb +24 -35
  419. data/spec/mongoid/relations/builders/referenced/many_spec.rb +15 -15
  420. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +18 -18
  421. data/spec/mongoid/relations/builders/referenced/one_spec.rb +12 -25
  422. data/spec/mongoid/relations/builders_spec.rb +21 -21
  423. data/spec/mongoid/relations/cascading/delete_spec.rb +9 -9
  424. data/spec/mongoid/relations/cascading/destroy_spec.rb +6 -6
  425. data/spec/mongoid/relations/cascading/nullify_spec.rb +4 -4
  426. data/spec/mongoid/relations/cascading/restrict_spec.rb +7 -7
  427. data/spec/mongoid/relations/cascading_spec.rb +16 -16
  428. data/spec/mongoid/relations/constraint_spec.rb +8 -7
  429. data/spec/mongoid/relations/conversions_spec.rb +16 -14
  430. data/spec/mongoid/relations/counter_cache_spec.rb +85 -0
  431. data/spec/mongoid/relations/cyclic_spec.rb +18 -18
  432. data/spec/mongoid/relations/eager/belongs_to_spec.rb +154 -0
  433. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +117 -0
  434. data/spec/mongoid/relations/eager/has_many_spec.rb +207 -0
  435. data/spec/mongoid/relations/eager/has_one_spec.rb +163 -0
  436. data/spec/mongoid/relations/eager_spec.rb +228 -0
  437. data/spec/mongoid/relations/embedded/dirty_spec.rb +8 -8
  438. data/spec/mongoid/relations/embedded/in_spec.rb +56 -57
  439. data/spec/mongoid/relations/embedded/many_spec.rb +467 -372
  440. data/spec/mongoid/relations/embedded/one_spec.rb +108 -141
  441. data/spec/mongoid/relations/macros_spec.rb +108 -102
  442. data/spec/mongoid/relations/metadata_spec.rb +180 -255
  443. data/spec/mongoid/relations/options_spec.rb +1 -1
  444. data/spec/mongoid/relations/polymorphic_spec.rb +13 -17
  445. data/spec/mongoid/relations/proxy_spec.rb +2 -2
  446. data/spec/mongoid/relations/referenced/in_spec.rb +128 -303
  447. data/spec/mongoid/relations/referenced/many_spec.rb +587 -527
  448. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +401 -424
  449. data/spec/mongoid/relations/referenced/one_spec.rb +149 -264
  450. data/spec/mongoid/relations/reflections_spec.rb +6 -6
  451. data/spec/mongoid/relations/synchronization_spec.rb +46 -50
  452. data/spec/mongoid/relations/targets/enumerable_spec.rb +118 -118
  453. data/spec/mongoid/relations/touchable_spec.rb +333 -0
  454. data/spec/mongoid/relations_spec.rb +16 -15
  455. data/spec/mongoid/{reloading_spec.rb → reloadable_spec.rb} +38 -55
  456. data/spec/mongoid/{scoping_spec.rb → scopable_spec.rb} +89 -164
  457. data/spec/mongoid/selectable_spec.rb +134 -0
  458. data/spec/mongoid/{serialization_spec.rb → serializable_spec.rb} +129 -82
  459. data/spec/mongoid/sessions/factory_spec.rb +49 -28
  460. data/spec/mongoid/sessions/mongo_uri_spec.rb +7 -7
  461. data/spec/mongoid/sessions/options_spec.rb +108 -0
  462. data/spec/mongoid/sessions_spec.rb +319 -178
  463. data/spec/mongoid/{sharding_spec.rb → shardable_spec.rb} +8 -8
  464. data/spec/mongoid/{state_spec.rb → stateful_spec.rb} +36 -11
  465. data/spec/mongoid/tasks/database_rake_spec.rb +285 -0
  466. data/spec/mongoid/tasks/database_spec.rb +160 -0
  467. data/spec/mongoid/threaded_spec.rb +17 -70
  468. data/spec/mongoid/timestamps/created/short_spec.rb +6 -6
  469. data/spec/mongoid/timestamps/created_spec.rb +5 -5
  470. data/spec/mongoid/timestamps/timeless_spec.rb +6 -6
  471. data/spec/mongoid/timestamps/updated/short_spec.rb +11 -11
  472. data/spec/mongoid/timestamps/updated_spec.rb +9 -13
  473. data/spec/mongoid/timestamps_spec.rb +9 -13
  474. data/spec/mongoid/{hierarchy_spec.rb → traversable_spec.rb} +19 -19
  475. data/spec/mongoid/{validations → validatable}/associated_spec.rb +45 -22
  476. data/spec/mongoid/{validations → validatable}/format_spec.rb +6 -6
  477. data/spec/mongoid/{validations → validatable}/length_spec.rb +14 -14
  478. data/spec/mongoid/{validations → validatable}/numericality_spec.rb +1 -1
  479. data/spec/mongoid/{validations → validatable}/presence_spec.rb +37 -44
  480. data/spec/mongoid/{validations → validatable}/uniqueness_spec.rb +184 -192
  481. data/spec/mongoid/{validations_spec.rb → validatable_spec.rb} +28 -28
  482. data/spec/mongoid_spec.rb +8 -8
  483. data/spec/rails/mongoid_spec.rb +19 -335
  484. data/spec/spec_helper.rb +31 -13
  485. metadata +303 -283
  486. data/lib/mongoid/atomic/positionable.rb +0 -73
  487. data/lib/mongoid/components.rb +0 -92
  488. data/lib/mongoid/config/inflections.rb +0 -6
  489. data/lib/mongoid/contextual/eager.rb +0 -158
  490. data/lib/mongoid/errors/versioning_not_on_root.rb +0 -23
  491. data/lib/mongoid/identity_map.rb +0 -163
  492. data/lib/mongoid/json.rb +0 -16
  493. data/lib/mongoid/matchers.rb +0 -32
  494. data/lib/mongoid/matchers/strategies.rb +0 -97
  495. data/lib/mongoid/multi_parameter_attributes.rb +0 -105
  496. data/lib/mongoid/nested_attributes.rb +0 -78
  497. data/lib/mongoid/observer.rb +0 -192
  498. data/lib/mongoid/paranoia.rb +0 -136
  499. data/lib/mongoid/persistence.rb +0 -357
  500. data/lib/mongoid/persistence/atomic.rb +0 -231
  501. data/lib/mongoid/persistence/atomic/add_to_set.rb +0 -47
  502. data/lib/mongoid/persistence/atomic/bit.rb +0 -35
  503. data/lib/mongoid/persistence/atomic/inc.rb +0 -45
  504. data/lib/mongoid/persistence/atomic/operation.rb +0 -154
  505. data/lib/mongoid/persistence/atomic/pop.rb +0 -32
  506. data/lib/mongoid/persistence/atomic/pull.rb +0 -32
  507. data/lib/mongoid/persistence/atomic/pull_all.rb +0 -32
  508. data/lib/mongoid/persistence/atomic/push.rb +0 -25
  509. data/lib/mongoid/persistence/atomic/push_all.rb +0 -25
  510. data/lib/mongoid/persistence/atomic/rename.rb +0 -30
  511. data/lib/mongoid/persistence/atomic/sets.rb +0 -28
  512. data/lib/mongoid/persistence/atomic/unset.rb +0 -27
  513. data/lib/mongoid/persistence/deletion.rb +0 -31
  514. data/lib/mongoid/persistence/insertion.rb +0 -38
  515. data/lib/mongoid/persistence/modification.rb +0 -35
  516. data/lib/mongoid/persistence/operations.rb +0 -214
  517. data/lib/mongoid/persistence/operations/embedded/insert.rb +0 -46
  518. data/lib/mongoid/persistence/operations/embedded/remove.rb +0 -43
  519. data/lib/mongoid/persistence/operations/insert.rb +0 -34
  520. data/lib/mongoid/persistence/operations/remove.rb +0 -33
  521. data/lib/mongoid/persistence/operations/update.rb +0 -59
  522. data/lib/mongoid/persistence/operations/upsert.rb +0 -28
  523. data/lib/mongoid/persistence/upsertion.rb +0 -31
  524. data/lib/mongoid/unit_of_work.rb +0 -61
  525. data/lib/mongoid/versioning.rb +0 -217
  526. data/lib/rack/mongoid.rb +0 -2
  527. data/lib/rack/mongoid/middleware/identity_map.rb +0 -39
  528. data/lib/rails/generators/mongoid/observer/observer_generator.rb +0 -17
  529. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +0 -4
  530. data/spec/app/models/actor_observer.rb +0 -15
  531. data/spec/app/models/callback_recorder.rb +0 -25
  532. data/spec/app/models/paranoid_phone.rb +0 -25
  533. data/spec/app/models/paranoid_post.rb +0 -36
  534. data/spec/app/models/phone_observer.rb +0 -6
  535. data/spec/mongoid/attributes/processing_spec.rb +0 -149
  536. data/spec/mongoid/criterion/destructive_spec.rb +0 -101
  537. data/spec/mongoid/criterion/modifiable_spec.rb +0 -409
  538. data/spec/mongoid/criterion/modification_spec.rb +0 -402
  539. data/spec/mongoid/errors/versioning_not_on_root_spec.rb +0 -29
  540. data/spec/mongoid/finders_spec.rb +0 -321
  541. data/spec/mongoid/identity_map_spec.rb +0 -564
  542. data/spec/mongoid/json_spec.rb +0 -33
  543. data/spec/mongoid/matchers/in_spec.rb +0 -25
  544. data/spec/mongoid/matchers/ne_spec.rb +0 -25
  545. data/spec/mongoid/matchers/nin_spec.rb +0 -25
  546. data/spec/mongoid/multi_parameter_attributes_spec.rb +0 -128
  547. data/spec/mongoid/observer_spec.rb +0 -290
  548. data/spec/mongoid/paranoia_spec.rb +0 -759
  549. data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +0 -262
  550. data/spec/mongoid/persistence/atomic/bit_spec.rb +0 -88
  551. data/spec/mongoid/persistence/atomic/inc_spec.rb +0 -133
  552. data/spec/mongoid/persistence/atomic/pop_spec.rb +0 -111
  553. data/spec/mongoid/persistence/atomic/pull_all_spec.rb +0 -77
  554. data/spec/mongoid/persistence/atomic/pull_spec.rb +0 -80
  555. data/spec/mongoid/persistence/atomic/push_all_spec.rb +0 -77
  556. data/spec/mongoid/persistence/atomic/push_spec.rb +0 -77
  557. data/spec/mongoid/persistence/atomic/rename_spec.rb +0 -42
  558. data/spec/mongoid/persistence/atomic/sets_spec.rb +0 -154
  559. data/spec/mongoid/persistence/atomic/unset_spec.rb +0 -65
  560. data/spec/mongoid/persistence/atomic_spec.rb +0 -216
  561. data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +0 -191
  562. data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +0 -8
  563. data/spec/mongoid/persistence/operations/insert_spec.rb +0 -149
  564. data/spec/mongoid/persistence/operations/remove_spec.rb +0 -113
  565. data/spec/mongoid/persistence/operations/update_spec.rb +0 -141
  566. data/spec/mongoid/persistence/operations/upsert_spec.rb +0 -59
  567. data/spec/mongoid/persistence/operations_spec.rb +0 -313
  568. data/spec/mongoid/persistence_spec.rb +0 -2279
  569. data/spec/mongoid/unit_of_work_spec.rb +0 -196
  570. data/spec/mongoid/versioning_spec.rb +0 -540
  571. data/spec/rack/mongoid/middleware/identity_map_spec.rb +0 -72
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for $rename operations.
6
+ #
7
+ # @since 4.0.0
8
+ module Renamable
9
+ extend ActiveSupport::Concern
10
+
11
+ # Rename fields from one value to another via $rename.
12
+ #
13
+ # @example Rename the fields.
14
+ # document.rename(title: "salutation", name: "nombre")
15
+ #
16
+ # @note This does not work for fields in embeds many relations.
17
+ #
18
+ # @param [ Hash ] renames The rename pairs of old name/new name.
19
+ #
20
+ # @return [ true, false ] If the rename suceeded.
21
+ #
22
+ # @since 4.0.0
23
+ def rename(renames)
24
+ prepare_atomic_operation do |ops|
25
+ process_atomic_operations(renames) do |old_field, new_field|
26
+ new_name = new_field.to_s
27
+ attributes[new_name] = attributes.delete(old_field)
28
+ ops[atomic_attribute_name(old_field)] = atomic_attribute_name(new_name)
29
+ end
30
+ { "$rename" => ops }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for persistence operations that save documents.
6
+ #
7
+ # @since 4.0.0
8
+ module Savable
9
+
10
+ # Save the document - will perform an insert if the document is new, and
11
+ # update if not.
12
+ #
13
+ # @example Save the document.
14
+ # document.save
15
+ #
16
+ # @param [ Hash ] options Options to pass to the save.
17
+ #
18
+ # @return [ true, false ] True is success, false if not.
19
+ #
20
+ # @since 1.0.0
21
+ def save(options = {})
22
+ if new_record?
23
+ !insert(options).new_record?
24
+ else
25
+ update_document(options)
26
+ end
27
+ end
28
+
29
+ # Save the document - will perform an insert if the document is new, and
30
+ # update if not. If a validation error occurs an error will get raised.
31
+ #
32
+ # @example Save the document.
33
+ # document.save!
34
+ #
35
+ # @param [ Hash ] options Options to pass to the save.
36
+ #
37
+ # @raise [ Errors::Validations ] If validation failed.
38
+ # @raise [ Errors::Callback ] If a callback returns false.
39
+ #
40
+ # @return [ true, false ] True if validation passed.
41
+ #
42
+ # @since 1.0.0
43
+ def save!(options = {})
44
+ unless save(options)
45
+ fail_due_to_validation! unless errors.empty?
46
+ fail_due_to_callback!(:save!)
47
+ end
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for $set operations.
6
+ #
7
+ # @since 4.0.0
8
+ module Settable
9
+ extend ActiveSupport::Concern
10
+
11
+ # Perform a $set operation on the provided field/value pairs and set the
12
+ # values in the document in memory.
13
+ #
14
+ # @example Set the values.
15
+ # document.set(title: "sir", dob: Date.new(1970, 1, 1))
16
+ #
17
+ # @param [ Hash ] setters The field/value pairs to set.
18
+ #
19
+ # @return [ true ] If the operation succeeded.
20
+ #
21
+ # @since 4.0.0
22
+ def set(setters)
23
+ prepare_atomic_operation do |ops|
24
+ process_atomic_operations(setters) do |field, value|
25
+ process_attribute(field.to_s, value)
26
+ ops[atomic_attribute_name(field)] = attributes[field]
27
+ end
28
+ { "$set" => ops }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for $unset operations.
6
+ #
7
+ # @since 4.0.0
8
+ module Unsettable
9
+ extend ActiveSupport::Concern
10
+
11
+ # Perform an $unset operation on the provided fields and in the
12
+ # values in the document in memory.
13
+ #
14
+ # @example Unset the values.
15
+ # document.unset(:first_name, :last_name, :middle)
16
+ #
17
+ # @param [ Array<String, Symbol> ] fields The names of the fields to
18
+ # unset.
19
+ #
20
+ # @return [ true ] If the operation succeeded.
21
+ #
22
+ # @since 4.0.0
23
+ def unset(*fields)
24
+ prepare_atomic_operation do |ops|
25
+ fields.flatten.each do |field|
26
+ normalized = database_field_name(field)
27
+ attributes.delete(normalized)
28
+ ops[atomic_attribute_name(normalized)] = true
29
+ end
30
+ { "$unset" => ops }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for persistence operations that update existing
6
+ # documents.
7
+ #
8
+ # @since 4.0.0
9
+ module Updatable
10
+
11
+ # Update a single attribute and persist the entire document.
12
+ # This skips validation but fires the callbacks.
13
+ #
14
+ # @example Update the attribute.
15
+ # person.update_attribute(:title, "Sir")
16
+ #
17
+ # @param [ Symbol, String ] name The name of the attribute.
18
+ # @param [ Object ] value The new value of the attribute.a
19
+ #
20
+ # @raise [ Errors::ReadonlyAttribute ] If the field cannot be changed due
21
+ # to being flagged as reaodnly.
22
+ #
23
+ # @return [ true, false ] True if save was successfull, false if not.
24
+ #
25
+ # @since 2.0.0
26
+ def update_attribute(name, value)
27
+ normalized = name.to_s
28
+ unless attribute_writable?(normalized)
29
+ raise Errors::ReadonlyAttribute.new(normalized, value)
30
+ end
31
+ setter = "#{normalized}="
32
+ if respond_to?(setter)
33
+ send(setter, value)
34
+ else
35
+ write_attribute(database_field_name(normalized), value)
36
+ end
37
+ save(validate: false)
38
+ end
39
+
40
+ # Update the document attributes in the database.
41
+ #
42
+ # @example Update the document's attributes
43
+ # document.update(:title => "Sir")
44
+ #
45
+ # @param [ Hash ] attributes The attributes to update.
46
+ #
47
+ # @return [ true, false ] True if validation passed, false if not.
48
+ #
49
+ # @since 1.0.0
50
+ def update(attributes = {})
51
+ assign_attributes(attributes)
52
+ save
53
+ end
54
+ alias :update_attributes :update
55
+
56
+ # Update the document attributes in the database and raise an error if
57
+ # validation failed.
58
+ #
59
+ # @example Update the document's attributes.
60
+ # document.update!(:title => "Sir")
61
+ #
62
+ # @param [ Hash ] attributes The attributes to update.
63
+ #
64
+ # @raise [ Errors::Validations ] If validation failed.
65
+ # @raise [ Errors::Callbacks ] If a callback returns false.
66
+ #
67
+ # @return [ true, false ] True if validation passed.
68
+ #
69
+ # @since 1.0.0
70
+ def update!(attributes = {})
71
+ result = update_attributes(attributes)
72
+ unless result
73
+ fail_due_to_validation! unless errors.empty?
74
+ fail_due_to_callback!(:update_attributes!)
75
+ end
76
+ result
77
+ end
78
+ alias :update_attributes! :update!
79
+
80
+ private
81
+
82
+ # Initialize the atomic updates.
83
+ #
84
+ # @api private
85
+ #
86
+ # @example Initialize the atomic updates.
87
+ # document.init_atomic_updates
88
+ #
89
+ # @return [ Array<Hash> ] The updates and conflicts.
90
+ #
91
+ # @since 4.0.0
92
+ def init_atomic_updates
93
+ updates = atomic_updates
94
+ conflicts = updates.delete(:conflicts) || {}
95
+ [ updates, conflicts ]
96
+ end
97
+
98
+ # Prepare the update for execution. Validates and runs callbacks, etc.
99
+ #
100
+ # @api private
101
+ #
102
+ # @example Prepare for update.
103
+ # document.prepare_update do
104
+ # collection.update(atomic_selector)
105
+ # end
106
+ #
107
+ # @param [ Hash ] options The options.
108
+ #
109
+ # @return [ true, false ] The result of the update.
110
+ #
111
+ # @since 4.0.0
112
+ def prepare_update(options = {})
113
+ return false if performing_validations?(options) &&
114
+ invalid?(options[:context] || :update)
115
+ process_flagged_destroys
116
+ result = run_callbacks(:save) do
117
+ run_callbacks(:update) do
118
+ yield(self)
119
+ true
120
+ end
121
+ end
122
+ post_process_persist(result, options) and result
123
+ end
124
+
125
+ # Update the document in the database.
126
+ #
127
+ # @example Update an existing document.
128
+ # document.update
129
+ #
130
+ # @param [ Hash ] options Options to pass to update.
131
+ #
132
+ # @option options [ true, false ] :validate Whether or not to validate.
133
+ #
134
+ # @return [ true, false ] True if succeeded, false if not.
135
+ #
136
+ # @since 1.0.0
137
+ def update_document(options = {})
138
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
139
+ prepare_update(options) do
140
+ updates, conflicts = init_atomic_updates
141
+ unless updates.empty?
142
+ coll = _root.collection
143
+ selector = atomic_selector
144
+ coll.find(selector).update(positionally(selector, updates))
145
+ conflicts.each_pair do |key, value|
146
+ coll.find(selector).update(positionally(selector, { key => value }))
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for persistence operations that upsert documents.
6
+ #
7
+ # @since 4.0.0
8
+ module Upsertable
9
+
10
+ # Perform an upsert of the document. If the document does not exist in the
11
+ # database, then Mongo will insert a new one, otherwise the fields will get
12
+ # overwritten with new values on the existing document.
13
+ #
14
+ # @example Upsert the document.
15
+ # document.upsert
16
+ #
17
+ # @param [ Hash ] options The validation options.
18
+ #
19
+ # @return [ true ] True.
20
+ #
21
+ # @since 3.0.0
22
+ def upsert(options = {})
23
+ prepare_upsert(options) do
24
+ collection.find(atomic_selector).update(as_document, [ :upsert ])
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ # Prepare the upsert for execution.
31
+ #
32
+ # @api private
33
+ #
34
+ # @example Prepare the upsert
35
+ # document.prepare_upsert do
36
+ # collection.find(selector).update(as_document)
37
+ # end
38
+ #
39
+ # @param [ Hash ] options The options hash.
40
+ #
41
+ # @return [ true, false ] If the operation succeeded.
42
+ #
43
+ # @since 4.0.0
44
+ def prepare_upsert(options = {})
45
+ return false if performing_validations?(options) && invalid?(:upsert)
46
+ result = run_callbacks(:upsert) do
47
+ yield(self)
48
+ true
49
+ end
50
+ self.new_record = false
51
+ post_process_persist(result, options) and result
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+
4
+ # This module is responsible for taking update selectors and switching out
5
+ # the indexes for the $ positional operator where appropriate.
6
+ #
7
+ # @since 4.0.0
8
+ module Positional
9
+
10
+ # Takes the provided selector and atomic operations and replaces the
11
+ # indexes of the embedded documents with the positional operator when
12
+ # needed.
13
+ #
14
+ # @note The only time we can accurately know when to use the positional
15
+ # operator is at the exact time we are going to persist something. So
16
+ # we can tell by the selector that we are sending if it is actually
17
+ # possible to use the positional operator at all. For example, if the
18
+ # selector is: { "_id" => 1 }, then we could not use the positional
19
+ # operator for updating embedded documents since there would never be a
20
+ # match - we base whether we can based on the number of levels deep the
21
+ # selector goes, and if the id values are not nil.
22
+ #
23
+ # @example Process the operations.
24
+ # positionally(
25
+ # { "_id" => 1, "addresses._id" => 2 },
26
+ # { "$set" => { "addresses.0.street" => "hobrecht" }}
27
+ # )
28
+ #
29
+ # @param [ Hash ] selector The selector.
30
+ # @param [ Hash ] operations The update operations.
31
+ # @param [ Hash ] processed The processed update operations.
32
+ #
33
+ # @return [ Hash ] The new operations.
34
+ #
35
+ # @since 3.1.0
36
+ def positionally(selector, operations, processed = {})
37
+ if selector.size == 1 || selector.values.any? { |val| val.nil? }
38
+ return operations
39
+ end
40
+ keys = selector.keys.map{ |m| m.sub('._id','') } - ['_id']
41
+ keys = keys.sort_by { |s| s.length*-1 }
42
+ process_operations(keys, operations, processed)
43
+ end
44
+
45
+ private
46
+
47
+ def process_operations(keys, operations, processed)
48
+ operations.each_pair do |operation, update|
49
+ processed[operation] = process_updates(keys, update)
50
+ end
51
+ processed
52
+ end
53
+
54
+ def process_updates(keys, update, updates = {})
55
+ update.each_pair do |position, value|
56
+ updates[replace_index(keys, position)] = value
57
+ end
58
+ updates
59
+ end
60
+
61
+ def replace_index(keys, position)
62
+ # replace to $ only if that key is on the selector
63
+ keys.each do |kk|
64
+ if position =~ /^#{kk}\.\d+\.(.*)/
65
+ return "#{kk}.$.#{$1}"
66
+ end
67
+ end
68
+ position
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,255 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+
4
+ # A cache of database queries on a per-request basis.
5
+ #
6
+ # @since 4.0.0
7
+ module QueryCache
8
+ class << self
9
+
10
+ # Get the cached queries.
11
+ #
12
+ # @example Get the cached queries from the current thread.
13
+ # QueryCache.cache_table
14
+ #
15
+ # @return [ Hash ] The hash of cached queries.
16
+ #
17
+ # @since 4.0.0
18
+ def cache_table
19
+ Thread.current["[mongoid]:query_cache"] ||= {}
20
+ end
21
+
22
+ # Clear the query cache.
23
+ #
24
+ # @example Clear the cache.
25
+ # QueryCache.clear_cache
26
+ #
27
+ # @return [ nil ] Always nil.
28
+ #
29
+ # @since 4.0.0
30
+ def clear_cache
31
+ Thread.current["[mongoid]:query_cache"] = nil
32
+ end
33
+
34
+ # Set whether the cache is enabled.
35
+ #
36
+ # @example Set if the cache is enabled.
37
+ # QueryCache.enabled = true
38
+ #
39
+ # @param [ true, false ] value The enabled value.
40
+ #
41
+ # @since 4.0.0
42
+ def enabled=(value)
43
+ Thread.current["[mongoid]:query_cache:enabled"] = value
44
+ end
45
+
46
+ # Is the query cache enabled on the current thread?
47
+ #
48
+ # @example Is the query cache enabled?
49
+ # QueryCache.enabled?
50
+ #
51
+ # @return [ true, false ] If the cache is enabled.
52
+ #
53
+ # @since 4.0.0
54
+ def enabled?
55
+ !!Thread.current["[mongoid]:query_cache:enabled"]
56
+ end
57
+
58
+ # Execute the block while using the query cache.
59
+ #
60
+ # @example Execute with the cache.
61
+ # QueryCache.cache { collection.find }
62
+ #
63
+ # @return [ Object ] The result of the block.
64
+ #
65
+ # @since 4.0.0
66
+ def cache
67
+ enabled = QueryCache.enabled?
68
+ QueryCache.enabled = true
69
+ yield
70
+ ensure
71
+ QueryCache.enabled = enabled
72
+ end
73
+ end
74
+
75
+ # The middleware to be added to a rack application in order to activate the
76
+ # query cache.
77
+ #
78
+ # @since 4.0.0
79
+ class Middleware
80
+
81
+ # Instantiate the middleware.
82
+ #
83
+ # @example Create the new middleware.
84
+ # Middleware.new(app)
85
+ #
86
+ # @param [ Object ] app The rack applciation stack.
87
+ #
88
+ # @since 4.0.0
89
+ def initialize(app)
90
+ @app = app
91
+ end
92
+
93
+ # Execute the request, wrapping in a query cache.
94
+ #
95
+ # @example Execute the request.
96
+ # middleware.call(env)
97
+ #
98
+ # @param [ Object ] env The environment.
99
+ #
100
+ # @return [ Object ] The result of the call.
101
+ #
102
+ # @since 4.0.0
103
+ def call(env)
104
+ QueryCache.cache { @app.call(env) }
105
+ ensure
106
+ QueryCache.clear_cache
107
+ end
108
+ end
109
+
110
+ module Base # :nodoc:
111
+
112
+ def alias_query_cache_clear(*method_names)
113
+ method_names.each do |method_name|
114
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
115
+ def #{method_name}_with_clear_cache(*args) # def upsert_with_clear_cache(*args)
116
+ QueryCache.clear_cache # QueryCache.clear_cache
117
+ #{method_name}_without_clear_cache(*args) # upsert_without_clear_cache(*args)
118
+ end # end
119
+ CODE
120
+
121
+ alias_method_chain method_name, :clear_cache
122
+ end
123
+ end
124
+ end
125
+
126
+ # Module to include in objects which need to wrap caching behaviour around
127
+ # them.
128
+ #
129
+ # @since 4.0.0
130
+ module Cacheable
131
+
132
+ private
133
+
134
+ def with_cache(context = :cursor, more = false, &block)
135
+ return yield unless QueryCache.enabled?
136
+ return yield if system_collection?
137
+ key = cache_key.push(context)
138
+
139
+ if more
140
+ docs = yield
141
+ QueryCache.cache_table[key].push(*docs)
142
+ docs
143
+ elsif QueryCache.cache_table.has_key?(key)
144
+ instrument(key) { QueryCache.cache_table[key] }
145
+ else
146
+ QueryCache.cache_table[key] = yield
147
+ end
148
+ end
149
+
150
+ def instrument(key, &block)
151
+ ActiveSupport::Notifications.instrument("query_cache.mongoid", key: key, &block)
152
+ end
153
+ end
154
+
155
+ # Adds behaviour around caching to a Moped Query object.
156
+ #
157
+ # @since 4.0.0
158
+ module Query
159
+ extend ActiveSupport::Concern
160
+ include Cacheable
161
+
162
+ included do
163
+ extend QueryCache::Base
164
+ alias_method_chain :cursor, :cache
165
+ alias_method_chain :first, :cache
166
+ alias_query_cache_clear :remove, :remove_all, :update, :update_all, :upsert
167
+ end
168
+
169
+ # Provide a wrapped query cache cursor.
170
+ #
171
+ # @example Get the wrapped caching cursor.
172
+ # query.cursor_with_cache
173
+ #
174
+ # @return [ CachedCursor ] The cached cursor.
175
+ #
176
+ # @since 4.0.0
177
+ def cursor_with_cache
178
+ CachedCursor.new(session, operation)
179
+ end
180
+
181
+ # Override first with caching.
182
+ #
183
+ # @example Get the first with a cache.
184
+ # query.first_with_cache
185
+ #
186
+ # @return [ Hash ] The first document.
187
+ #
188
+ # @since 4.0.0
189
+ def first_with_cache
190
+ with_cache(:first) do
191
+ first_without_cache
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ def cache_key
198
+ [ operation.database, operation.collection, operation.selector, operation.limit, operation.skip, operation.fields ]
199
+ end
200
+
201
+ def system_collection?
202
+ operation.collection =~ /^system./
203
+ end
204
+ end
205
+
206
+ # Adds behaviour to the query cache for collections.
207
+ #
208
+ # @since 4.0.0
209
+ module Collection
210
+ extend ActiveSupport::Concern
211
+
212
+ included do
213
+ extend QueryCache::Base
214
+ alias_query_cache_clear :insert
215
+ end
216
+ end
217
+
218
+ # A Cursor that attempts to load documents from memory first before hitting
219
+ # the database if the same query has already been executed.
220
+ #
221
+ # @since 4.0.0
222
+ class CachedCursor < Moped::Cursor
223
+ include Cacheable
224
+
225
+ # Override the loading of docs to attempt to fetch from the cache.
226
+ #
227
+ # @example Load the documents.
228
+ # cursor.load_docs
229
+ #
230
+ # @return [ Array<Hash> ] The documents.
231
+ #
232
+ # @since 4.0.0
233
+ def load_docs
234
+ with_cache { super }
235
+ end
236
+
237
+ def get_more
238
+ with_cache(:cursor, true) { super }
239
+ end
240
+
241
+ private
242
+
243
+ def cache_key
244
+ [ @database, @collection, @selector, @options[:limit], @options[:skip], @options[:fields] ]
245
+ end
246
+
247
+ def system_collection?
248
+ @collection =~ /^system./
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ Moped::Query.__send__(:include, Mongoid::QueryCache::Query)
255
+ Moped::Collection.__send__(:include, Mongoid::QueryCache::Collection)