mongoid 3.1.7 → 4.0.0.alpha1

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 (521) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +317 -11
  3. data/README.md +4 -5
  4. data/lib/config/locales/en.yml +9 -12
  5. data/lib/mongoid.rb +6 -75
  6. data/lib/mongoid/atomic.rb +0 -11
  7. data/lib/mongoid/atomic/paths/embedded.rb +0 -30
  8. data/lib/mongoid/atomic/paths/root.rb +0 -13
  9. data/lib/mongoid/attributes.rb +30 -108
  10. data/lib/mongoid/attributes/dynamic.rb +154 -0
  11. data/lib/mongoid/attributes/nested.rb +82 -0
  12. data/lib/mongoid/attributes/processing.rb +13 -66
  13. data/lib/mongoid/{dirty.rb → changeable.rb} +5 -2
  14. data/lib/mongoid/composable.rb +104 -0
  15. data/lib/mongoid/config.rb +3 -9
  16. data/lib/mongoid/config/options.rb +1 -1
  17. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -9
  18. data/lib/mongoid/contextual/atomic.rb +53 -53
  19. data/lib/mongoid/contextual/command.rb +26 -0
  20. data/lib/mongoid/contextual/map_reduce.rb +1 -1
  21. data/lib/mongoid/contextual/memory.rb +6 -5
  22. data/lib/mongoid/contextual/mongo.rb +59 -28
  23. data/lib/mongoid/contextual/text_search.rb +180 -0
  24. data/lib/mongoid/copyable.rb +2 -3
  25. data/lib/mongoid/criteria.rb +13 -33
  26. data/lib/mongoid/criteria/{#findable.rb# → findable.rb} +0 -2
  27. data/lib/mongoid/{criterion/inspection.rb → criteria/inspectable.rb} +2 -2
  28. data/lib/mongoid/{criterion → criteria}/marshalable.rb +3 -1
  29. data/lib/mongoid/{criterion → criteria}/modifiable.rb +1 -1
  30. data/lib/mongoid/{criterion/scoping.rb → criteria/scopable.rb} +2 -2
  31. data/lib/mongoid/document.rb +28 -12
  32. data/lib/mongoid/errors.rb +1 -1
  33. data/lib/mongoid/errors/document_not_found.rb +2 -1
  34. data/lib/mongoid/errors/invalid_value.rb +16 -0
  35. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  36. data/lib/mongoid/extensions.rb +2 -7
  37. data/lib/mongoid/extensions/array.rb +2 -2
  38. data/lib/mongoid/extensions/boolean.rb +14 -17
  39. data/lib/mongoid/extensions/float.rb +1 -0
  40. data/lib/mongoid/extensions/hash.rb +1 -1
  41. data/lib/mongoid/extensions/object.rb +4 -4
  42. data/lib/mongoid/extensions/object_id.rb +5 -5
  43. data/lib/mongoid/extensions/range.rb +8 -2
  44. data/lib/mongoid/extensions/string.rb +5 -17
  45. data/lib/mongoid/extensions/time.rb +2 -2
  46. data/lib/mongoid/factory.rb +3 -3
  47. data/lib/mongoid/fields.rb +9 -8
  48. data/lib/mongoid/fields/foreign_key.rb +3 -3
  49. data/lib/mongoid/fields/standard.rb +4 -16
  50. data/lib/mongoid/fields/validators/macro.rb +11 -3
  51. data/lib/mongoid/{finders.rb → findable.rb} +6 -2
  52. data/lib/mongoid/{indexes.rb → indexable.rb} +50 -55
  53. data/lib/mongoid/indexable/specification.rb +104 -0
  54. data/lib/mongoid/{indexes → indexable}/validators/options.rb +2 -1
  55. data/lib/mongoid/{inspection.rb → inspectable.rb} +15 -11
  56. data/lib/mongoid/{callbacks.rb → interceptable.rb} +3 -52
  57. data/lib/mongoid/log_subscriber.rb +22 -0
  58. data/lib/mongoid/matchable.rb +152 -0
  59. data/lib/mongoid/{matchers → matchable}/all.rb +1 -1
  60. data/lib/mongoid/{matchers → matchable}/and.rb +2 -2
  61. data/lib/mongoid/{matchers → matchable}/default.rb +1 -1
  62. data/lib/mongoid/{matchers → matchable}/exists.rb +1 -1
  63. data/lib/mongoid/{matchers → matchable}/gt.rb +1 -1
  64. data/lib/mongoid/{matchers → matchable}/gte.rb +1 -1
  65. data/lib/mongoid/{matchers → matchable}/in.rb +2 -2
  66. data/lib/mongoid/{matchers → matchable}/lt.rb +1 -1
  67. data/lib/mongoid/{matchers → matchable}/lte.rb +1 -1
  68. data/lib/mongoid/{matchers → matchable}/ne.rb +1 -1
  69. data/lib/mongoid/{matchers → matchable}/nin.rb +3 -2
  70. data/lib/mongoid/{matchers → matchable}/or.rb +2 -2
  71. data/lib/mongoid/{matchers → matchable}/size.rb +1 -1
  72. data/lib/mongoid/persistable.rb +212 -0
  73. data/lib/mongoid/persistable/creatable.rb +188 -0
  74. data/lib/mongoid/persistable/deletable.rb +148 -0
  75. data/lib/mongoid/persistable/destroyable.rb +55 -0
  76. data/lib/mongoid/persistable/incrementable.rb +36 -0
  77. data/lib/mongoid/persistable/logical.rb +38 -0
  78. data/lib/mongoid/persistable/poppable.rb +39 -0
  79. data/lib/mongoid/persistable/pullable.rb +55 -0
  80. data/lib/mongoid/persistable/pushable.rb +62 -0
  81. data/lib/mongoid/persistable/renamable.rb +35 -0
  82. data/lib/mongoid/persistable/savable.rb +52 -0
  83. data/lib/mongoid/persistable/settable.rb +33 -0
  84. data/lib/mongoid/persistable/unsettable.rb +36 -0
  85. data/lib/mongoid/persistable/updatable.rb +151 -0
  86. data/lib/mongoid/persistable/upsertable.rb +55 -0
  87. data/lib/mongoid/positional.rb +71 -0
  88. data/lib/mongoid/railtie.rb +32 -45
  89. data/lib/mongoid/railties/database.rake +12 -6
  90. data/lib/mongoid/relations.rb +3 -3
  91. data/lib/mongoid/relations/accessors.rb +13 -46
  92. data/lib/mongoid/relations/auto_save.rb +15 -36
  93. data/lib/mongoid/relations/binding.rb +0 -23
  94. data/lib/mongoid/relations/bindings/embedded/many.rb +1 -3
  95. data/lib/mongoid/relations/bindings/referenced/in.rb +3 -8
  96. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -1
  97. data/lib/mongoid/relations/builder.rb +1 -1
  98. data/lib/mongoid/relations/builders.rb +2 -2
  99. data/lib/mongoid/relations/builders/nested_attributes/many.rb +10 -13
  100. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -5
  101. data/lib/mongoid/relations/builders/referenced/in.rb +1 -1
  102. data/lib/mongoid/relations/builders/referenced/many.rb +1 -2
  103. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +1 -2
  104. data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
  105. data/lib/mongoid/relations/cascading.rb +3 -5
  106. data/lib/mongoid/relations/constraint.rb +1 -1
  107. data/lib/mongoid/relations/conversions.rb +1 -1
  108. data/lib/mongoid/relations/counter_cache.rb +39 -15
  109. data/lib/mongoid/relations/eager.rb +47 -0
  110. data/lib/mongoid/relations/eager/base.rb +57 -0
  111. data/lib/mongoid/relations/eager/belongs_to.rb +30 -0
  112. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +40 -0
  113. data/lib/mongoid/relations/eager/has_many.rb +37 -0
  114. data/lib/mongoid/relations/eager/has_one.rb +29 -0
  115. data/lib/mongoid/relations/embedded/batchable.rb +3 -4
  116. data/lib/mongoid/relations/embedded/many.rb +7 -27
  117. data/lib/mongoid/relations/macros.rb +2 -4
  118. data/lib/mongoid/relations/many.rb +30 -31
  119. data/lib/mongoid/relations/metadata.rb +6 -75
  120. data/lib/mongoid/relations/nested_builder.rb +2 -2
  121. data/lib/mongoid/relations/options.rb +1 -0
  122. data/lib/mongoid/relations/polymorphic.rb +0 -1
  123. data/lib/mongoid/relations/proxy.rb +10 -32
  124. data/lib/mongoid/relations/referenced/in.rb +2 -18
  125. data/lib/mongoid/relations/referenced/many.rb +9 -22
  126. data/lib/mongoid/relations/referenced/many_to_many.rb +10 -33
  127. data/lib/mongoid/relations/referenced/one.rb +2 -21
  128. data/lib/mongoid/relations/synchronization.rb +3 -3
  129. data/lib/mongoid/relations/touchable.rb +33 -0
  130. data/lib/mongoid/{reloading.rb → reloadable.rb} +6 -4
  131. data/lib/mongoid/{scoping.rb → scopable.rb} +26 -3
  132. data/lib/mongoid/selectable.rb +59 -0
  133. data/lib/mongoid/{serialization.rb → serializable.rb} +10 -1
  134. data/lib/mongoid/sessions.rb +37 -345
  135. data/lib/mongoid/sessions/factory.rb +2 -0
  136. data/lib/mongoid/sessions/options.rb +176 -0
  137. data/lib/mongoid/sessions/storage_options.rb +140 -0
  138. data/lib/mongoid/sessions/thread_options.rb +19 -0
  139. data/lib/mongoid/sessions/validators/storage.rb +15 -1
  140. data/lib/mongoid/{sharding.rb → shardable.rb} +5 -1
  141. data/lib/mongoid/support/query_counter.rb +23 -0
  142. data/lib/mongoid/threaded.rb +0 -110
  143. data/lib/mongoid/threaded/lifecycle.rb +0 -28
  144. data/lib/mongoid/timestamps/updated/short.rb +2 -2
  145. data/lib/mongoid/{hierarchy.rb → traversable.rb} +9 -5
  146. data/lib/mongoid/{validations.rb → validatable.rb} +23 -9
  147. data/lib/mongoid/{validations → validatable}/associated.rb +3 -1
  148. data/lib/mongoid/{validations → validatable}/format.rb +1 -1
  149. data/lib/mongoid/{validations → validatable}/length.rb +1 -1
  150. data/lib/mongoid/{validations → validatable}/localizable.rb +1 -1
  151. data/lib/mongoid/{validations → validatable}/macros.rb +4 -3
  152. data/lib/mongoid/{validations → validatable}/presence.rb +1 -1
  153. data/lib/mongoid/{validations → validatable}/queryable.rb +1 -2
  154. data/lib/mongoid/{validations → validatable}/uniqueness.rb +3 -3
  155. data/lib/mongoid/version.rb +1 -1
  156. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +9 -13
  157. data/lib/rails/generators/mongoid/model/model_generator.rb +0 -1
  158. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +0 -3
  159. data/lib/rails/generators/mongoid_generator.rb +3 -40
  160. data/lib/rails/mongoid.rb +59 -57
  161. data/lib/support/ruby_version.rb +1 -1
  162. data/spec/app/models/account.rb +2 -6
  163. data/spec/app/models/acolyte.rb +1 -0
  164. data/spec/app/models/actor.rb +0 -1
  165. data/spec/app/models/address.rb +6 -1
  166. data/spec/app/models/animal.rb +1 -1
  167. data/spec/app/models/appointment.rb +2 -2
  168. data/spec/app/models/article.rb +1 -4
  169. data/spec/app/models/audio.rb +5 -0
  170. data/spec/app/models/author.rb +0 -2
  171. data/spec/app/models/band.rb +3 -2
  172. data/spec/app/models/bar.rb +1 -0
  173. data/spec/app/models/book.rb +1 -0
  174. data/spec/app/models/building.rb +0 -2
  175. data/spec/app/models/building_address.rb +0 -2
  176. data/spec/app/models/bus.rb +1 -1
  177. data/spec/app/models/canvas.rb +1 -1
  178. data/spec/app/models/contractor.rb +0 -2
  179. data/spec/app/models/country_code.rb +1 -1
  180. data/spec/app/models/definition.rb +2 -2
  181. data/spec/app/models/dragon.rb +4 -0
  182. data/spec/app/models/drug.rb +1 -3
  183. data/spec/app/models/dungeon.rb +4 -0
  184. data/spec/app/models/filesystem.rb +1 -0
  185. data/spec/app/models/fish.rb +0 -1
  186. data/spec/app/models/fruits.rb +6 -0
  187. data/spec/app/models/game.rb +0 -2
  188. data/spec/app/models/house.rb +0 -2
  189. data/spec/app/models/item.rb +1 -5
  190. data/spec/app/models/jar.rb +1 -1
  191. data/spec/app/models/label.rb +4 -4
  192. data/spec/app/models/login.rb +1 -1
  193. data/spec/app/models/movie.rb +1 -0
  194. data/spec/app/models/name.rb +3 -3
  195. data/spec/app/models/note.rb +1 -1
  196. data/spec/app/models/oscar.rb +1 -1
  197. data/spec/app/models/parent_doc.rb +1 -1
  198. data/spec/app/models/person.rb +13 -8
  199. data/spec/app/models/phone.rb +1 -3
  200. data/spec/app/models/player.rb +1 -1
  201. data/spec/app/models/post.rb +2 -1
  202. data/spec/app/models/quiz.rb +0 -3
  203. data/spec/app/models/record.rb +5 -5
  204. data/spec/app/models/registry.rb +1 -1
  205. data/spec/app/models/server.rb +1 -1
  206. data/spec/app/models/service.rb +3 -3
  207. data/spec/app/models/sound.rb +5 -0
  208. data/spec/app/models/template.rb +1 -1
  209. data/spec/app/models/title.rb +0 -1
  210. data/spec/app/models/track.rb +5 -5
  211. data/spec/app/models/tree.rb +1 -1
  212. data/spec/app/models/video.rb +0 -4
  213. data/spec/app/models/wiki_page.rb +1 -4
  214. data/spec/app/models/word.rb +3 -0
  215. data/spec/app/models/word_origin.rb +1 -1
  216. data/spec/config/mongoid.yml +7 -8
  217. data/spec/helpers.rb +18 -0
  218. data/spec/mongoid/atomic/modifiers_spec.rb +22 -22
  219. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +8 -49
  220. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +7 -49
  221. data/spec/mongoid/atomic/paths/root_spec.rb +3 -61
  222. data/spec/mongoid/atomic/paths_spec.rb +19 -19
  223. data/spec/mongoid/atomic_spec.rb +19 -19
  224. data/spec/mongoid/{nested_attributes_spec.rb → attributes/nested_spec.rb} +335 -448
  225. data/spec/mongoid/attributes/readonly_spec.rb +16 -16
  226. data/spec/mongoid/attributes_spec.rb +188 -434
  227. data/spec/mongoid/{dirty_spec.rb → changeable_spec.rb} +117 -148
  228. data/spec/mongoid/{components_spec.rb → composable_spec.rb} +3 -3
  229. data/spec/mongoid/config/environment_spec.rb +3 -3
  230. data/spec/mongoid/config/options_spec.rb +6 -6
  231. data/spec/mongoid/config_spec.rb +24 -48
  232. data/spec/mongoid/contextual/aggregable/memory_spec.rb +12 -12
  233. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +46 -38
  234. data/spec/mongoid/contextual/atomic_spec.rb +60 -56
  235. data/spec/mongoid/contextual/find_and_modify_spec.rb +14 -14
  236. data/spec/mongoid/contextual/geo_near_spec.rb +22 -22
  237. data/spec/mongoid/contextual/map_reduce_spec.rb +27 -27
  238. data/spec/mongoid/contextual/memory_spec.rb +94 -94
  239. data/spec/mongoid/contextual/mongo_spec.rb +225 -139
  240. data/spec/mongoid/contextual/text_search_spec.rb +207 -0
  241. data/spec/mongoid/copyable_spec.rb +56 -68
  242. data/spec/mongoid/criteria/findable_spec.rb +991 -0
  243. data/spec/mongoid/{criterion/inspection_spec.rb → criteria/inspectable_spec.rb} +5 -5
  244. data/spec/mongoid/{criterion → criteria}/marshalable_spec.rb +2 -2
  245. data/spec/mongoid/criteria/modifiable_spec.rb +1063 -0
  246. data/spec/mongoid/{criterion/scoping_spec.rb → criteria/scopable_spec.rb} +31 -31
  247. data/spec/mongoid/criteria_spec.rb +530 -2207
  248. data/spec/mongoid/document_spec.rb +166 -120
  249. data/spec/mongoid/equality_spec.rb +22 -22
  250. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +3 -3
  251. data/spec/mongoid/errors/callback_spec.rb +3 -3
  252. data/spec/mongoid/errors/delete_restriction_spec.rb +3 -3
  253. data/spec/mongoid/errors/document_not_found_spec.rb +11 -11
  254. data/spec/mongoid/errors/eager_load_spec.rb +3 -3
  255. data/spec/mongoid/errors/invalid_collection_spec.rb +3 -3
  256. data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -3
  257. data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -3
  258. data/spec/mongoid/errors/invalid_field_spec.rb +3 -3
  259. data/spec/mongoid/errors/invalid_find_spec.rb +3 -3
  260. data/spec/mongoid/errors/invalid_includes_spec.rb +3 -3
  261. data/spec/mongoid/errors/invalid_index_spec.rb +3 -3
  262. data/spec/mongoid/errors/invalid_options_spec.rb +3 -3
  263. data/spec/mongoid/errors/invalid_path_spec.rb +3 -3
  264. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -3
  265. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -3
  266. data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -3
  267. data/spec/mongoid/errors/invalid_time_spec.rb +3 -3
  268. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -3
  269. data/spec/mongoid/errors/mixed_relations_spec.rb +3 -3
  270. data/spec/mongoid/errors/mixed_session_configuration_spec.rb +3 -3
  271. data/spec/mongoid/errors/mongoid_error_spec.rb +7 -7
  272. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +3 -3
  273. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  274. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -3
  275. data/spec/mongoid/errors/no_metadata_spec.rb +3 -3
  276. data/spec/mongoid/errors/no_parent_spec.rb +3 -3
  277. data/spec/mongoid/errors/no_session_config_spec.rb +3 -3
  278. data/spec/mongoid/errors/no_session_database_spec.rb +3 -3
  279. data/spec/mongoid/errors/no_session_hosts_spec.rb +3 -3
  280. data/spec/mongoid/errors/no_sessions_config_spec.rb +3 -3
  281. data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -3
  282. data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -3
  283. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -3
  284. data/spec/mongoid/errors/unknown_attribute_spec.rb +5 -5
  285. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -3
  286. data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -3
  287. data/spec/mongoid/errors/validations_spec.rb +7 -7
  288. data/spec/mongoid/extensions/array_spec.rb +61 -61
  289. data/spec/mongoid/extensions/big_decimal_spec.rb +11 -11
  290. data/spec/mongoid/extensions/binary_spec.rb +12 -12
  291. data/spec/mongoid/extensions/boolean_spec.rb +18 -18
  292. data/spec/mongoid/extensions/date_spec.rb +13 -13
  293. data/spec/mongoid/extensions/date_time_spec.rb +9 -9
  294. data/spec/mongoid/extensions/false_class_spec.rb +5 -5
  295. data/spec/mongoid/extensions/float_spec.rb +29 -15
  296. data/spec/mongoid/extensions/hash_spec.rb +29 -29
  297. data/spec/mongoid/extensions/integer_spec.rb +15 -15
  298. data/spec/mongoid/extensions/module_spec.rb +2 -2
  299. data/spec/mongoid/extensions/nil_class_spec.rb +1 -1
  300. data/spec/mongoid/extensions/object_id_spec.rb +134 -134
  301. data/spec/mongoid/extensions/object_spec.rb +26 -26
  302. data/spec/mongoid/extensions/range_spec.rb +61 -12
  303. data/spec/mongoid/extensions/regexp_spec.rb +4 -4
  304. data/spec/mongoid/extensions/set_spec.rb +4 -4
  305. data/spec/mongoid/extensions/string_spec.rb +35 -46
  306. data/spec/mongoid/extensions/symbol_spec.rb +9 -9
  307. data/spec/mongoid/extensions/time_spec.rb +49 -49
  308. data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -34
  309. data/spec/mongoid/extensions/true_class_spec.rb +5 -5
  310. data/spec/mongoid/extensions_spec.rb +15 -0
  311. data/spec/mongoid/factory_spec.rb +15 -15
  312. data/spec/mongoid/fields/foreign_key_spec.rb +73 -66
  313. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +15 -15
  314. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +22 -22
  315. data/spec/mongoid/fields/localized_spec.rb +23 -23
  316. data/spec/mongoid/fields/standard_spec.rb +12 -12
  317. data/spec/mongoid/fields_spec.rb +168 -209
  318. data/spec/mongoid/{finders_spec.rb → findable_spec.rb} +62 -27
  319. data/spec/mongoid/indexable/specification_spec.rb +102 -0
  320. data/spec/mongoid/{indexes_spec.rb → indexable_spec.rb} +171 -51
  321. data/spec/mongoid/{inspection_spec.rb → inspectable_spec.rb} +6 -14
  322. data/spec/mongoid/{callbacks_spec.rb → interceptable_spec.rb} +105 -105
  323. data/spec/mongoid/log_subscriber_spec.rb +74 -0
  324. data/spec/mongoid/loggable_spec.rb +1 -1
  325. data/spec/mongoid/{matchers → matchable}/all_spec.rb +4 -4
  326. data/spec/mongoid/{matchers → matchable}/and_spec.rb +11 -11
  327. data/spec/mongoid/{matchers → matchable}/default_spec.rb +15 -15
  328. data/spec/mongoid/{matchers → matchable}/exists_spec.rb +5 -5
  329. data/spec/mongoid/{matchers → matchable}/gt_spec.rb +9 -8
  330. data/spec/mongoid/{matchers → matchable}/gte_spec.rb +7 -7
  331. data/spec/mongoid/matchable/in_spec.rb +49 -0
  332. data/spec/mongoid/{matchers → matchable}/lt_spec.rb +7 -7
  333. data/spec/mongoid/{matchers → matchable}/lte_spec.rb +7 -7
  334. data/spec/mongoid/{matchers → matchable}/ne_spec.rb +3 -3
  335. data/spec/mongoid/matchable/nin_spec.rb +48 -0
  336. data/spec/mongoid/{matchers → matchable}/or_spec.rb +6 -6
  337. data/spec/mongoid/{matchers → matchable}/size_spec.rb +3 -3
  338. data/spec/mongoid/{matchers_spec.rb → matchable_spec.rb} +41 -41
  339. data/spec/mongoid/persistable/creatable_spec.rb +512 -0
  340. data/spec/mongoid/persistable/deletable_spec.rb +205 -0
  341. data/spec/mongoid/persistable/destroyable_spec.rb +148 -0
  342. data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
  343. data/spec/mongoid/persistable/logical_spec.rb +143 -0
  344. data/spec/mongoid/persistable/poppable_spec.rb +115 -0
  345. data/spec/mongoid/persistable/pullable_spec.rb +228 -0
  346. data/spec/mongoid/persistable/pushable_spec.rb +258 -0
  347. data/spec/mongoid/persistable/renamable_spec.rb +135 -0
  348. data/spec/mongoid/persistable/savable_spec.rb +432 -0
  349. data/spec/mongoid/persistable/settable_spec.rb +139 -0
  350. data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
  351. data/spec/mongoid/persistable/updatable_spec.rb +558 -0
  352. data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
  353. data/spec/mongoid/persistable_spec.rb +206 -0
  354. data/spec/mongoid/{atomic/positionable_spec.rb → positional_spec.rb} +19 -14
  355. data/spec/mongoid/railties/document_spec.rb +2 -2
  356. data/spec/mongoid/relations/accessors_spec.rb +53 -145
  357. data/spec/mongoid/relations/auto_save_spec.rb +36 -16
  358. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +6 -6
  359. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +2 -2
  360. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +3 -3
  361. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +12 -12
  362. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +6 -6
  363. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +9 -9
  364. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +6 -6
  365. data/spec/mongoid/relations/builders/embedded/in_spec.rb +4 -4
  366. data/spec/mongoid/relations/builders/embedded/many_spec.rb +18 -18
  367. data/spec/mongoid/relations/builders/embedded/one_spec.rb +11 -11
  368. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +12 -13
  369. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +14 -14
  370. data/spec/mongoid/relations/builders/referenced/in_spec.rb +22 -33
  371. data/spec/mongoid/relations/builders/referenced/many_spec.rb +15 -15
  372. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +18 -18
  373. data/spec/mongoid/relations/builders/referenced/one_spec.rb +11 -24
  374. data/spec/mongoid/relations/builders_spec.rb +21 -21
  375. data/spec/mongoid/relations/cascading/delete_spec.rb +7 -7
  376. data/spec/mongoid/relations/cascading/destroy_spec.rb +2 -2
  377. data/spec/mongoid/relations/cascading/nullify_spec.rb +2 -2
  378. data/spec/mongoid/relations/cascading/restrict_spec.rb +3 -3
  379. data/spec/mongoid/relations/cascading_spec.rb +16 -16
  380. data/spec/mongoid/relations/constraint_spec.rb +8 -7
  381. data/spec/mongoid/relations/conversions_spec.rb +16 -14
  382. data/spec/mongoid/relations/counter_cache_spec.rb +85 -0
  383. data/spec/mongoid/relations/cyclic_spec.rb +18 -18
  384. data/spec/mongoid/relations/eager/belongs_to_spec.rb +154 -0
  385. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +143 -0
  386. data/spec/mongoid/relations/eager/has_many_spec.rb +207 -0
  387. data/spec/mongoid/relations/eager/has_one_spec.rb +163 -0
  388. data/spec/mongoid/relations/eager_spec.rb +228 -0
  389. data/spec/mongoid/relations/embedded/dirty_spec.rb +8 -8
  390. data/spec/mongoid/relations/embedded/in_spec.rb +55 -56
  391. data/spec/mongoid/relations/embedded/many_spec.rb +357 -367
  392. data/spec/mongoid/relations/embedded/one_spec.rb +98 -139
  393. data/spec/mongoid/relations/macros_spec.rb +108 -102
  394. data/spec/mongoid/relations/metadata_spec.rb +147 -241
  395. data/spec/mongoid/relations/options_spec.rb +1 -1
  396. data/spec/mongoid/relations/polymorphic_spec.rb +13 -17
  397. data/spec/mongoid/relations/proxy_spec.rb +2 -2
  398. data/spec/mongoid/relations/referenced/in_spec.rb +128 -303
  399. data/spec/mongoid/relations/referenced/many_spec.rb +379 -522
  400. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +345 -417
  401. data/spec/mongoid/relations/referenced/one_spec.rb +148 -263
  402. data/spec/mongoid/relations/reflections_spec.rb +6 -6
  403. data/spec/mongoid/relations/synchronization_spec.rb +46 -50
  404. data/spec/mongoid/relations/targets/enumerable_spec.rb +116 -116
  405. data/spec/mongoid/relations/touchable_spec.rb +296 -0
  406. data/spec/mongoid/relations_spec.rb +16 -15
  407. data/spec/mongoid/{reloading_spec.rb → reloadable_spec.rb} +20 -60
  408. data/spec/mongoid/{scoping_spec.rb → scopable_spec.rb} +74 -126
  409. data/spec/mongoid/selectable_spec.rb +134 -0
  410. data/spec/mongoid/{serialization_spec.rb → serializable_spec.rb} +111 -82
  411. data/spec/mongoid/sessions/factory_spec.rb +49 -28
  412. data/spec/mongoid/sessions/mongo_uri_spec.rb +7 -7
  413. data/spec/mongoid/sessions/options_spec.rb +92 -0
  414. data/spec/mongoid/sessions_spec.rb +288 -177
  415. data/spec/mongoid/{sharding_spec.rb → shardable_spec.rb} +8 -8
  416. data/spec/mongoid/state_spec.rb +10 -10
  417. data/spec/mongoid/threaded_spec.rb +17 -70
  418. data/spec/mongoid/timestamps/created/short_spec.rb +6 -6
  419. data/spec/mongoid/timestamps/created_spec.rb +5 -5
  420. data/spec/mongoid/timestamps/updated/short_spec.rb +10 -10
  421. data/spec/mongoid/timestamps/updated_spec.rb +8 -12
  422. data/spec/mongoid/timestamps_spec.rb +7 -11
  423. data/spec/mongoid/{hierarchy_spec.rb → traversable_spec.rb} +19 -19
  424. data/spec/mongoid/{validations → validatable}/associated_spec.rb +18 -18
  425. data/spec/mongoid/{validations → validatable}/format_spec.rb +6 -6
  426. data/spec/mongoid/{validations → validatable}/length_spec.rb +7 -7
  427. data/spec/mongoid/{validations → validatable}/numericality_spec.rb +1 -1
  428. data/spec/mongoid/{validations → validatable}/presence_spec.rb +31 -38
  429. data/spec/mongoid/{validations → validatable}/uniqueness_spec.rb +126 -183
  430. data/spec/mongoid/{validations_spec.rb → validatable_spec.rb} +28 -28
  431. data/spec/mongoid_spec.rb +8 -8
  432. data/spec/rails/mongoid_spec.rb +72 -87
  433. data/spec/spec_helper.rb +19 -17
  434. metadata +261 -283
  435. data/lib/mongoid/atomic/positionable.rb +0 -73
  436. data/lib/mongoid/components.rb +0 -92
  437. data/lib/mongoid/config/inflections.rb +0 -6
  438. data/lib/mongoid/contextual/eager.rb +0 -158
  439. data/lib/mongoid/criterion/findable.rb +0 -179
  440. data/lib/mongoid/errors/versioning_not_on_root.rb +0 -23
  441. data/lib/mongoid/identity_map.rb +0 -163
  442. data/lib/mongoid/json.rb +0 -16
  443. data/lib/mongoid/matchers.rb +0 -32
  444. data/lib/mongoid/matchers/strategies.rb +0 -97
  445. data/lib/mongoid/multi_parameter_attributes.rb +0 -105
  446. data/lib/mongoid/nested_attributes.rb +0 -78
  447. data/lib/mongoid/observer.rb +0 -192
  448. data/lib/mongoid/paranoia.rb +0 -136
  449. data/lib/mongoid/persistence.rb +0 -357
  450. data/lib/mongoid/persistence/atomic.rb +0 -231
  451. data/lib/mongoid/persistence/atomic/add_to_set.rb +0 -47
  452. data/lib/mongoid/persistence/atomic/bit.rb +0 -35
  453. data/lib/mongoid/persistence/atomic/inc.rb +0 -45
  454. data/lib/mongoid/persistence/atomic/operation.rb +0 -154
  455. data/lib/mongoid/persistence/atomic/pop.rb +0 -32
  456. data/lib/mongoid/persistence/atomic/pull.rb +0 -32
  457. data/lib/mongoid/persistence/atomic/pull_all.rb +0 -32
  458. data/lib/mongoid/persistence/atomic/push.rb +0 -25
  459. data/lib/mongoid/persistence/atomic/push_all.rb +0 -25
  460. data/lib/mongoid/persistence/atomic/rename.rb +0 -30
  461. data/lib/mongoid/persistence/atomic/sets.rb +0 -28
  462. data/lib/mongoid/persistence/atomic/unset.rb +0 -27
  463. data/lib/mongoid/persistence/deletion.rb +0 -31
  464. data/lib/mongoid/persistence/insertion.rb +0 -38
  465. data/lib/mongoid/persistence/modification.rb +0 -35
  466. data/lib/mongoid/persistence/operations.rb +0 -214
  467. data/lib/mongoid/persistence/operations/embedded/insert.rb +0 -46
  468. data/lib/mongoid/persistence/operations/embedded/remove.rb +0 -43
  469. data/lib/mongoid/persistence/operations/insert.rb +0 -34
  470. data/lib/mongoid/persistence/operations/remove.rb +0 -33
  471. data/lib/mongoid/persistence/operations/update.rb +0 -59
  472. data/lib/mongoid/persistence/operations/upsert.rb +0 -28
  473. data/lib/mongoid/persistence/upsertion.rb +0 -31
  474. data/lib/mongoid/unit_of_work.rb +0 -61
  475. data/lib/mongoid/versioning.rb +0 -217
  476. data/lib/rack/mongoid.rb +0 -2
  477. data/lib/rack/mongoid/middleware/identity_map.rb +0 -39
  478. data/lib/rails/generators/mongoid/observer/observer_generator.rb +0 -17
  479. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +0 -4
  480. data/spec/app/models/actor_observer.rb +0 -15
  481. data/spec/app/models/callback_recorder.rb +0 -25
  482. data/spec/app/models/draft.rb +0 -9
  483. data/spec/app/models/paranoid_phone.rb +0 -25
  484. data/spec/app/models/paranoid_post.rb +0 -36
  485. data/spec/app/models/phone_observer.rb +0 -6
  486. data/spec/mongoid/#atomic_spec.rb# +0 -365
  487. data/spec/mongoid/attributes/processing_spec.rb +0 -149
  488. data/spec/mongoid/criterion/destructive_spec.rb +0 -101
  489. data/spec/mongoid/criterion/modifiable_spec.rb +0 -409
  490. data/spec/mongoid/criterion/modification_spec.rb +0 -402
  491. data/spec/mongoid/errors/versioning_not_on_root_spec.rb +0 -29
  492. data/spec/mongoid/identity_map_spec.rb +0 -564
  493. data/spec/mongoid/json_spec.rb +0 -33
  494. data/spec/mongoid/matchers/in_spec.rb +0 -25
  495. data/spec/mongoid/matchers/nin_spec.rb +0 -25
  496. data/spec/mongoid/multi_parameter_attributes_spec.rb +0 -128
  497. data/spec/mongoid/observer_spec.rb +0 -290
  498. data/spec/mongoid/paranoia_spec.rb +0 -759
  499. data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +0 -262
  500. data/spec/mongoid/persistence/atomic/bit_spec.rb +0 -88
  501. data/spec/mongoid/persistence/atomic/inc_spec.rb +0 -133
  502. data/spec/mongoid/persistence/atomic/pop_spec.rb +0 -111
  503. data/spec/mongoid/persistence/atomic/pull_all_spec.rb +0 -77
  504. data/spec/mongoid/persistence/atomic/pull_spec.rb +0 -80
  505. data/spec/mongoid/persistence/atomic/push_all_spec.rb +0 -77
  506. data/spec/mongoid/persistence/atomic/push_spec.rb +0 -77
  507. data/spec/mongoid/persistence/atomic/rename_spec.rb +0 -42
  508. data/spec/mongoid/persistence/atomic/sets_spec.rb +0 -154
  509. data/spec/mongoid/persistence/atomic/unset_spec.rb +0 -65
  510. data/spec/mongoid/persistence/atomic_spec.rb +0 -216
  511. data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +0 -191
  512. data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +0 -8
  513. data/spec/mongoid/persistence/operations/insert_spec.rb +0 -149
  514. data/spec/mongoid/persistence/operations/remove_spec.rb +0 -113
  515. data/spec/mongoid/persistence/operations/update_spec.rb +0 -141
  516. data/spec/mongoid/persistence/operations/upsert_spec.rb +0 -59
  517. data/spec/mongoid/persistence/operations_spec.rb +0 -313
  518. data/spec/mongoid/persistence_spec.rb +0 -2279
  519. data/spec/mongoid/unit_of_work_spec.rb +0 -196
  520. data/spec/mongoid/versioning_spec.rb +0 -540
  521. data/spec/rack/mongoid/middleware/identity_map_spec.rb +0 -72
@@ -1,192 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid
3
-
4
- # Observer classes respond to life cycle callbacks to implement trigger-like
5
- # behavior outside the original class. This is a great way to reduce the
6
- # clutter that normally comes when the model class is burdened with
7
- # functionality that doesn't pertain to the core responsibility of the
8
- # class. Mongoid's observers work similar to ActiveRecord's. Example:
9
- #
10
- # class CommentObserver < Mongoid::Observer
11
- # def after_save(comment)
12
- # Notifications.comment(
13
- # "admin@do.com", "New comment was posted", comment
14
- # ).deliver
15
- # end
16
- # end
17
- #
18
- # This Observer sends an email when a Comment#save is finished.
19
- #
20
- # class ContactObserver < Mongoid::Observer
21
- # def after_create(contact)
22
- # contact.logger.info('New contact added!')
23
- # end
24
- #
25
- # def after_destroy(contact)
26
- # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!")
27
- # end
28
- # end
29
- #
30
- # This Observer uses logger to log when specific callbacks are triggered.
31
- #
32
- # == Observing a class that can't be inferred
33
- #
34
- # Observers will by default be mapped to the class with which they share a
35
- # name. So CommentObserver will be tied to observing Comment,
36
- # ProductManagerObserver to ProductManager, and so on. If you want to
37
- # name your observer differently than the class you're interested in
38
- # observing, you can use the Observer.observe class method which takes
39
- # either the concrete class (Product) or a symbol for that class (:product):
40
- #
41
- # class AuditObserver < Mongoid::Observer
42
- # observe :account
43
- #
44
- # def after_update(account)
45
- # AuditTrail.new(account, "UPDATED")
46
- # end
47
- # end
48
- #
49
- # If the audit observer needs to watch more than one kind of object,
50
- # this can be specified with multiple arguments:
51
- #
52
- # class AuditObserver < Mongoid::Observer
53
- # observe :account, :balance
54
- #
55
- # def after_update(record)
56
- # AuditTrail.new(record, "UPDATED")
57
- # end
58
- # end
59
- #
60
- # The AuditObserver will now act on both updates to Account and Balance
61
- # by treating them both as records.
62
- #
63
- # == Available callback methods
64
- #
65
- # * after_initialize
66
- # * before_validation
67
- # * after_validation
68
- # * before_create
69
- # * around_create
70
- # * after_create
71
- # * before_update
72
- # * around_update
73
- # * after_update
74
- # * before_upsert
75
- # * around_upsert
76
- # * after_upsert
77
- # * before_save
78
- # * around_save
79
- # * after_save
80
- # * before_destroy
81
- # * around_destroy
82
- # * after_destroy
83
- #
84
- # == Storing Observers in Rails
85
- #
86
- # If you're using Mongoid within Rails, observer classes are usually stored
87
- # in +app/models+ with the naming convention of +app/models/audit_observer.rb+.
88
- #
89
- # == Configuration
90
- #
91
- # In order to activate an observer, list it in the +config.mongoid.observers+
92
- # configuration setting in your +config/application.rb+ file.
93
- #
94
- # config.mongoid.observers = :comment_observer, :signup_observer
95
- #
96
- # Observers will not be invoked unless you define them in your
97
- # application configuration.
98
- #
99
- # == Loading
100
- #
101
- # Observers register themselves with the model class that they observe,
102
- # since it is the class that notifies them of events when they occur.
103
- # As a side-effect, when an observer is loaded, its corresponding model
104
- # class is loaded.
105
- #
106
- # Observers are loaded after the application initializers, so that
107
- # observed models can make use of extensions. If by any chance you are
108
- # using observed models in the initialization, you can
109
- # still load their observers by calling +ModelObserver.instance+ before.
110
- # Observers are singletons and that call instantiates and registers them.
111
- class Observer < ActiveModel::Observer
112
-
113
- private
114
-
115
- # Adds the specified observer to the class.
116
- #
117
- # @example Add the observer.
118
- # observer.add_observer!(Document)
119
- #
120
- # @param [ Class ] klass The child observer to add.
121
- #
122
- # @since 2.0.0.rc.8
123
- def add_observer!(klass)
124
- super and define_callbacks(klass)
125
- end
126
-
127
- # Defines all the callbacks for each observer of the model.
128
- #
129
- # @example Define all the callbacks.
130
- # observer.define_callbacks(Document)
131
- #
132
- # @param [ Class ] klass The model to define them on.
133
- #
134
- # @since 2.0.0.rc.8
135
- def define_callbacks(klass)
136
- observer = self
137
- observer_name = observer.class.name.underscore.gsub('/', '__')
138
- Mongoid::Callbacks.observables.each do |callback|
139
- next unless respond_to?(callback)
140
- callback_meth = :"_notify_#{observer_name}_for_#{callback}"
141
- unless klass.respond_to?(callback_meth)
142
- klass.send(:define_method, callback_meth) do |&block|
143
- if value = observer.update(callback, self, &block)
144
- value
145
- else
146
- block.call if block
147
- end
148
- end
149
- klass.send(callback, callback_meth)
150
- end
151
- end
152
- self
153
- end
154
-
155
- # Are the observers disabled for the object?
156
- #
157
- # @api private
158
- #
159
- # @example If the observer disabled?
160
- # Observer.disabled_for(band)
161
- #
162
- # @param [ Document ] object The model instance.
163
- #
164
- # @return [ true, false ] If the observer is disabled.
165
- def disabled_for?(object)
166
- klass = object.class
167
- return false unless klass.respond_to?(:observers)
168
- klass.observers.disabled_for?(self) || Mongoid.observers.disabled_for?(self)
169
- end
170
-
171
- class << self
172
-
173
- # Attaches the observer to the specified classes.
174
- #
175
- # @example Attach the BandObserver to the class Artist.
176
- # class BandObserver < Mongoid::Observer
177
- # observe :artist
178
- # end
179
- #
180
- # @param [ Array<Symbol> ] models The names of the models.
181
- #
182
- # @since 3.0.15
183
- def observe(*models)
184
- models.flatten!
185
- models.collect! do |model|
186
- model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model
187
- end
188
- singleton_class.redefine_method(:observed_classes) { models }
189
- end
190
- end
191
- end
192
- end
@@ -1,136 +0,0 @@
1
- # encoding: utf-8
2
- module Mongoid
3
-
4
- # Include this module to get soft deletion of root level documents.
5
- # This will add a deleted_at field to the +Document+, managed automatically.
6
- # Potentially incompatible with unique indices. (if collisions with deleted items)
7
- #
8
- # @example Make a document paranoid.
9
- # class Person
10
- # include Mongoid::Document
11
- # include Mongoid::Paranoia
12
- # end
13
- module Paranoia
14
- extend ActiveSupport::Concern
15
-
16
- included do
17
- field :deleted_at, type: Time
18
- self.paranoid = true
19
-
20
- default_scope where(deleted_at: nil)
21
- scope :deleted, ne(deleted_at: nil)
22
- end
23
-
24
- # Delete the paranoid +Document+ from the database completely. This will
25
- # run the destroy callbacks.
26
- #
27
- # @example Hard destroy the document.
28
- # document.destroy!
29
- #
30
- # @return [ true, false ] If the operation succeeded.
31
- #
32
- # @since 1.0.0
33
- def destroy!
34
- run_callbacks(:destroy) { delete! }
35
- end
36
-
37
- # Delete the paranoid +Document+ from the database completely.
38
- #
39
- # @example Hard delete the document.
40
- # document.delete!
41
- #
42
- # @return [ true, false ] If the operation succeeded.
43
- #
44
- # @since 1.0.0
45
- def delete!
46
- Persistence::Operations.remove(self).persist
47
- end
48
-
49
- # Delete the +Document+, will set the deleted_at timestamp and not actually
50
- # delete it.
51
- #
52
- # @example Soft remove the document.
53
- # document.remove
54
- #
55
- # @param [ Hash ] options The database options.
56
- #
57
- # @return [ true ] True.
58
- #
59
- # @since 1.0.0
60
- def remove(options = {})
61
- cascade!
62
- time = self.deleted_at = Time.now
63
- paranoid_collection.find(atomic_selector).
64
- update({ "$set" => { paranoid_field => time }})
65
- @destroyed = true
66
- IdentityMap.remove(self)
67
- true
68
- end
69
- alias :delete :remove
70
-
71
- # Determines if this document is destroyed.
72
- #
73
- # @example Is the document destroyed?
74
- # person.destroyed?
75
- #
76
- # @return [ true, false ] If the document is destroyed.
77
- #
78
- # @since 1.0.0
79
- def destroyed?
80
- (@destroyed ||= false) || !!deleted_at
81
- end
82
- alias :deleted? :destroyed?
83
-
84
- def persisted?
85
- !new_record? && !(@destroyed ||= false)
86
- end
87
-
88
- # Restores a previously soft-deleted document. Handles this by removing the
89
- # deleted_at flag.
90
- #
91
- # @example Restore the document from deleted state.
92
- # document.restore
93
- #
94
- # @return [ Time ] The time the document had been deleted.
95
- #
96
- # @since 1.0.0
97
- def restore
98
- paranoid_collection.find(atomic_selector).
99
- update({ "$unset" => { paranoid_field => true }})
100
- attributes.delete("deleted_at")
101
- @destroyed = false
102
- true
103
- end
104
-
105
- # Returns a string representing the documents's key suitable for use in URLs.
106
- def to_param
107
- new_record? ? nil : to_key.join('-')
108
- end
109
-
110
- private
111
-
112
- # Get the collection to be used for paranoid operations.
113
- #
114
- # @example Get the paranoid collection.
115
- # document.paranoid_collection
116
- #
117
- # @return [ Collection ] The root collection.
118
- #
119
- # @since 2.3.1
120
- def paranoid_collection
121
- embedded? ? _root.collection : self.collection
122
- end
123
-
124
- # Get the field to be used for paranoid operations.
125
- #
126
- # @example Get the paranoid field.
127
- # document.paranoid_field
128
- #
129
- # @return [ String ] The deleted at field.
130
- #
131
- # @since 2.3.1
132
- def paranoid_field
133
- embedded? ? "#{atomic_position}.deleted_at" : "deleted_at"
134
- end
135
- end
136
- end
@@ -1,357 +0,0 @@
1
- # encoding: utf-8
2
- require "mongoid/persistence/atomic"
3
- require "mongoid/persistence/deletion"
4
- require "mongoid/persistence/insertion"
5
- require "mongoid/persistence/modification"
6
- require "mongoid/persistence/upsertion"
7
- require "mongoid/persistence/operations"
8
-
9
- module Mongoid
10
-
11
- # The persistence module is a mixin to provide database accessor methods for
12
- # the document. These correspond to the appropriate accessors on a
13
- # mongo collection and retain the same DSL.
14
- #
15
- # @example Sample persistence operations.
16
- # document.insert
17
- # document.update
18
- # document.upsert
19
- module Persistence
20
- extend ActiveSupport::Concern
21
- include Atomic
22
- include Mongoid::Atomic::Positionable
23
-
24
- # The atomic operations that deal with arrays or sets in the db.
25
- #
26
- # @since 4.0.0
27
- LIST_OPERATIONS = [ "$addToSet", "$push", "$pull", "$pullAll" ].freeze
28
-
29
- # Remove the document from the database with callbacks.
30
- #
31
- # @example Destroy a document.
32
- # document.destroy
33
- #
34
- # @param [ Hash ] options Options to pass to destroy.
35
- #
36
- # @return [ true, false ] True if successful, false if not.
37
- def destroy(options = {})
38
- self.flagged_for_destroy = true
39
- result = run_callbacks(:destroy) do
40
- remove(options)
41
- end
42
- self.flagged_for_destroy = false
43
- result
44
- end
45
-
46
- # Insert a new document into the database. Will return the document
47
- # itself whether or not the save was successful.
48
- #
49
- # @example Insert a document.
50
- # document.insert
51
- #
52
- # @param [ Hash ] options Options to pass to insert.
53
- #
54
- # @return [ Document ] The persisted document.
55
- def insert(options = {})
56
- Operations.insert(self, options).persist
57
- end
58
-
59
- # Remove the document from the database.
60
- #
61
- # @example Remove the document.
62
- # document.remove
63
- #
64
- # @param [ Hash ] options Options to pass to remove.
65
- #
66
- # @return [ TrueClass ] True.
67
- def remove(options = {})
68
- Operations.remove(self, options).persist
69
- end
70
- alias :delete :remove
71
-
72
- # Save the document - will perform an insert if the document is new, and
73
- # update if not.
74
- #
75
- # @example Save the document.
76
- # document.save
77
- #
78
- # @param [ Hash ] options Options to pass to the save.
79
- #
80
- # @return [ true, false ] True is success, false if not.
81
- #
82
- # @since 1.0.0
83
- def save(options = {})
84
- if new_record?
85
- !insert(options).new_record?
86
- else
87
- update(options)
88
- end
89
- end
90
-
91
- # Save the document - will perform an insert if the document is new, and
92
- # update if not. If a validation error occurs an error will get raised.
93
- #
94
- # @example Save the document.
95
- # document.save!
96
- #
97
- # @param [ Hash ] options Options to pass to the save.
98
- #
99
- # @return [ true, false ] True if validation passed.
100
- def save!(options = {})
101
- unless save(options)
102
- self.class.fail_validate!(self) unless errors.empty?
103
- self.class.fail_callback!(self, :save!)
104
- end
105
- return true
106
- end
107
-
108
- # Touch the document, in effect updating its updated_at timestamp and
109
- # optionally the provided field to the current time. If any belongs_to
110
- # relations exist with a touch option, they will be updated as well.
111
- #
112
- # @example Update the updated_at timestamp.
113
- # document.touch
114
- #
115
- # @example Update the updated_at and provided timestamps.
116
- # document.touch(:audited)
117
- #
118
- # @note This will not autobuild relations if those options are set.
119
- #
120
- # @param [ Symbol ] field The name of an additional field to update.
121
- #
122
- # @return [ true/false ] false if record is new_record otherwise true.
123
- #
124
- # @since 3.0.0
125
- def touch(field = nil)
126
- return false if _root.new_record?
127
- current = Time.now
128
- field = database_field_name(field)
129
- write_attribute(:updated_at, current) if respond_to?("updated_at=")
130
- write_attribute(field, current) if field
131
-
132
- touches = touch_atomic_updates(field)
133
- unless touches.empty?
134
- selector = atomic_selector
135
- _root.collection.find(selector).update(positionally(selector, touches))
136
- end
137
- run_callbacks(:touch, :after)
138
- true
139
- end
140
-
141
- # Update the document in the database.
142
- #
143
- # @example Update an existing document.
144
- # document.update
145
- #
146
- # @param [ Hash ] options Options to pass to update.
147
- #
148
- # @return [ true, false ] True if succeeded, false if not.
149
- def update(options = {})
150
- Operations.update(self, options).persist
151
- end
152
-
153
- # Update a single attribute and persist the entire document.
154
- # This skips validation but fires the callbacks.
155
- #
156
- # @example Update the attribute.
157
- # person.update_attribute(:title, "Sir")
158
- #
159
- # @param [ Symbol, String ] name The name of the attribute.
160
- # @param [ Object ] value The new value of the attribute.a
161
- #
162
- # @raise [ Errors::ReadonlyAttribute ] If the field cannot be changed due
163
- # to being flagged as reaodnly.
164
- #
165
- # @return [ true, false ] True if save was successfull, false if not.
166
- #
167
- # @since 2.0.0.rc.6
168
- def update_attribute(name, value)
169
- normalized = name.to_s
170
- unless attribute_writable?(normalized)
171
- raise Errors::ReadonlyAttribute.new(normalized, value)
172
- end
173
- write_attribute(database_field_name(normalized), value)
174
- save(validate: false)
175
- end
176
-
177
- # Update the document attributes in the database.
178
- #
179
- # @example Update the document's attributes
180
- # document.update_attributes(:title => "Sir")
181
- #
182
- # @param [ Hash ] attributes The attributes to update.
183
- #
184
- # @return [ true, false ] True if validation passed, false if not.
185
- def update_attributes(attributes = {}, options = {})
186
- assign_attributes(attributes, options); save
187
- end
188
-
189
- # Update the document attributes in the database and raise an error if
190
- # validation failed.
191
- #
192
- # @example Update the document's attributes.
193
- # document.update_attributes(:title => "Sir")
194
- #
195
- # @param [ Hash ] attributes The attributes to update.
196
- #
197
- # @raise [ Errors::Validations ] If validation failed.
198
- #
199
- # @return [ true, false ] True if validation passed.
200
- def update_attributes!(attributes = {}, options = {})
201
- result = update_attributes(attributes, options)
202
- unless result
203
- self.class.fail_validate!(self) unless errors.empty?
204
- self.class.fail_callback!(self, :update_attributes!)
205
- end
206
- result
207
- end
208
-
209
- # Perform an upsert of the document. If the document does not exist in the
210
- # database, then Mongo will insert a new one, otherwise the fields will get
211
- # overwritten with new values on the existing document.
212
- #
213
- # @example Upsert the document.
214
- # document.upsert
215
- #
216
- # @param [ Hash ] options The validation options.
217
- #
218
- # @return [ true ] True.
219
- #
220
- # @since 3.0.0
221
- def upsert(options = {})
222
- Operations.upsert(self, options).persist
223
- end
224
-
225
- module ClassMethods #:nodoc:
226
-
227
- # Create a new document. This will instantiate a new document and
228
- # insert it in a single call. Will always return the document
229
- # whether save passed or not.
230
- #
231
- # @example Create a new document.
232
- # Person.create(:title => "Mr")
233
- #
234
- # @example Create multiple new documents.
235
- # Person.create({ title: "Mr" }, { title: "Mrs" })
236
- #
237
- # @param [ Hash, Array ] attributes The attributes to create with, or an
238
- # Array of multiple attributes for multiple documents.
239
- # @param [ Hash ] options A mass-assignment protection options. Supports
240
- # :as and :without_protection
241
- #
242
- # @return [ Document, Array<Document> ] The newly created document(s).
243
- #
244
- # @since 1.0.0
245
- def create(attributes = nil, options = {}, &block)
246
- _creating do
247
- if attributes.is_a?(::Array)
248
- attributes.map { |attrs| create(attrs, options, &block) }
249
- else
250
- doc = new(attributes, options, &block)
251
- doc.save
252
- doc
253
- end
254
- end
255
- end
256
-
257
- # Create a new document. This will instantiate a new document and
258
- # insert it in a single call. Will always return the document
259
- # whether save passed or not, and if validation fails an error will be
260
- # raise.
261
- #
262
- # @example Create a new document.
263
- # Person.create!(:title => "Mr")
264
- #
265
- # @example Create multiple new documents.
266
- # Person.create!({ title: "Mr" }, { title: "Mrs" })
267
- #
268
- # @param [ Hash, Array ] attributes The attributes to create with, or an
269
- # Array of multiple attributes for multiple documents.
270
- # @param [ Hash ] options A mass-assignment protection options. Supports
271
- # :as and :without_protection
272
- #
273
- # @return [ Document, Array<Document> ] The newly created document(s).
274
- #
275
- # @since 1.0.0
276
- def create!(attributes = {}, options = {}, &block)
277
- _creating do
278
- if attributes.is_a?(::Array)
279
- attributes.map { |attrs| create!(attrs, options, &block) }
280
- else
281
- doc = new(attributes, options, &block)
282
- fail_validate!(doc) unless doc.insert.errors.empty?
283
- fail_callback!(doc, :create!) if doc.new_record?
284
- doc
285
- end
286
- end
287
- end
288
-
289
- # Delete all documents given the supplied conditions. If no conditions
290
- # are passed, the entire collection will be dropped for performance
291
- # benefits. Does not fire any callbacks.
292
- #
293
- # @example Delete matching documents from the collection.
294
- # Person.delete_all(:conditions => { :title => "Sir" })
295
- #
296
- # @example Delete all documents from the collection.
297
- # Person.delete_all
298
- #
299
- # @param [ Hash ] conditions Optional conditions to delete by.
300
- #
301
- # @return [ Integer ] The number of documents deleted.
302
- def delete_all(conditions = nil)
303
- conds = conditions || {}
304
- selector = conds[:conditions] || conds
305
- selector.merge!(_type: name) if hereditary?
306
- coll = collection
307
- deleted = coll.find(selector).count
308
- coll.find(selector).remove_all
309
- deleted
310
- end
311
-
312
- # Delete all documents given the supplied conditions. If no conditions
313
- # are passed, the entire collection will be dropped for performance
314
- # benefits. Fires the destroy callbacks if conditions were passed.
315
- #
316
- # @example Destroy matching documents from the collection.
317
- # Person.destroy_all(:conditions => { :title => "Sir" })
318
- #
319
- # @example Destroy all documents from the collection.
320
- # Person.destroy_all
321
- #
322
- # @param [ Hash ] conditions Optional conditions to destroy by.
323
- #
324
- # @return [ Integer ] The number of documents destroyed.
325
- def destroy_all(conditions = nil)
326
- conds = conditions || {}
327
- documents = where(conds[:conditions] || conds)
328
- destroyed = documents.count
329
- documents.each { |doc| doc.destroy }
330
- destroyed
331
- end
332
-
333
- # Raise an error if validation failed.
334
- #
335
- # @example Raise the validation error.
336
- # Person.fail_validate!(person)
337
- #
338
- # @param [ Document ] document The document to fail.
339
- def fail_validate!(document)
340
- raise Errors::Validations.new(document)
341
- end
342
-
343
- # Raise an error if a callback failed.
344
- #
345
- # @example Raise the callback error.
346
- # Person.fail_callback!(person, :create!)
347
- #
348
- # @param [ Document ] document The document to fail.
349
- # @param [ Symbol ] method The method being called.
350
- #
351
- # @since 2.2.0
352
- def fail_callback!(document, method)
353
- raise Errors::Callback.new(document.class, method)
354
- end
355
- end
356
- end
357
- end