mongoid 3.1.6 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +432 -8
  3. data/README.md +5 -6
  4. data/lib/config/locales/en.yml +32 -18
  5. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  6. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  7. data/lib/mongoid/atomic/paths/embedded.rb +0 -30
  8. data/lib/mongoid/atomic/paths/root.rb +0 -13
  9. data/lib/mongoid/atomic.rb +1 -12
  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/attributes.rb +63 -101
  14. data/lib/mongoid/{dirty.rb → changeable.rb} +32 -2
  15. data/lib/mongoid/composable.rb +105 -0
  16. data/lib/mongoid/config/options.rb +1 -1
  17. data/lib/mongoid/config.rb +3 -9
  18. data/lib/mongoid/contextual/aggregable/mongo.rb +7 -9
  19. data/lib/mongoid/contextual/atomic.rb +53 -53
  20. data/lib/mongoid/contextual/geo_near.rb +1 -1
  21. data/lib/mongoid/contextual/map_reduce.rb +4 -2
  22. data/lib/mongoid/contextual/memory.rb +18 -6
  23. data/lib/mongoid/contextual/mongo.rb +64 -56
  24. data/lib/mongoid/contextual/none.rb +90 -0
  25. data/lib/mongoid/contextual/text_search.rb +178 -0
  26. data/lib/mongoid/contextual.rb +2 -0
  27. data/lib/mongoid/copyable.rb +2 -3
  28. data/lib/mongoid/{criterion → criteria}/findable.rb +7 -47
  29. data/lib/mongoid/{criterion/inspection.rb → criteria/inspectable.rb} +2 -2
  30. data/lib/mongoid/{criterion → criteria}/marshalable.rb +3 -1
  31. data/lib/mongoid/{criterion → criteria}/modifiable.rb +28 -8
  32. data/lib/mongoid/criteria/permission.rb +70 -0
  33. data/lib/mongoid/{criterion/scoping.rb → criteria/scopable.rb} +2 -2
  34. data/lib/mongoid/criteria.rb +39 -34
  35. data/lib/mongoid/document.rb +32 -17
  36. data/lib/mongoid/errors/document_not_destroyed.rb +25 -0
  37. data/lib/mongoid/errors/document_not_found.rb +2 -1
  38. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  39. data/lib/mongoid/errors/invalid_storage_parent.rb +26 -0
  40. data/lib/mongoid/errors/invalid_value.rb +16 -0
  41. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  42. data/lib/mongoid/errors/readonly_document.rb +24 -0
  43. data/lib/mongoid/errors.rb +4 -1
  44. data/lib/mongoid/extensions/array.rb +3 -3
  45. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  46. data/lib/mongoid/extensions/boolean.rb +15 -17
  47. data/lib/mongoid/extensions/date.rb +1 -1
  48. data/lib/mongoid/extensions/date_time.rb +3 -3
  49. data/lib/mongoid/extensions/float.rb +2 -1
  50. data/lib/mongoid/extensions/hash.rb +3 -3
  51. data/lib/mongoid/extensions/integer.rb +1 -1
  52. data/lib/mongoid/extensions/object.rb +7 -7
  53. data/lib/mongoid/extensions/object_id.rb +5 -5
  54. data/lib/mongoid/extensions/range.rb +9 -3
  55. data/lib/mongoid/extensions/regexp.rb +1 -1
  56. data/lib/mongoid/extensions/set.rb +1 -1
  57. data/lib/mongoid/extensions/string.rb +6 -18
  58. data/lib/mongoid/extensions/symbol.rb +1 -1
  59. data/lib/mongoid/extensions/time.rb +3 -3
  60. data/lib/mongoid/extensions/time_with_zone.rb +1 -1
  61. data/lib/mongoid/extensions.rb +2 -7
  62. data/lib/mongoid/factory.rb +8 -6
  63. data/lib/mongoid/fields/foreign_key.rb +3 -3
  64. data/lib/mongoid/fields/localized.rb +1 -1
  65. data/lib/mongoid/fields/standard.rb +5 -17
  66. data/lib/mongoid/fields/validators/macro.rb +15 -5
  67. data/lib/mongoid/fields.rb +41 -8
  68. data/lib/mongoid/{finders.rb → findable.rb} +8 -2
  69. data/lib/mongoid/indexable/specification.rb +104 -0
  70. data/lib/mongoid/{indexes → indexable}/validators/options.rb +2 -1
  71. data/lib/mongoid/{indexes.rb → indexable.rb} +50 -55
  72. data/lib/mongoid/{inspection.rb → inspectable.rb} +15 -11
  73. data/lib/mongoid/{callbacks.rb → interceptable.rb} +30 -62
  74. data/lib/mongoid/log_subscriber.rb +55 -0
  75. data/lib/mongoid/{matchers → matchable}/all.rb +1 -1
  76. data/lib/mongoid/{matchers → matchable}/and.rb +2 -2
  77. data/lib/mongoid/{matchers → matchable}/default.rb +1 -1
  78. data/lib/mongoid/{matchers → matchable}/exists.rb +1 -1
  79. data/lib/mongoid/{matchers → matchable}/gt.rb +1 -1
  80. data/lib/mongoid/{matchers → matchable}/gte.rb +1 -1
  81. data/lib/mongoid/{matchers → matchable}/in.rb +2 -2
  82. data/lib/mongoid/{matchers → matchable}/lt.rb +1 -1
  83. data/lib/mongoid/{matchers → matchable}/lte.rb +1 -1
  84. data/lib/mongoid/{matchers → matchable}/ne.rb +2 -2
  85. data/lib/mongoid/{matchers → matchable}/nin.rb +3 -2
  86. data/lib/mongoid/{matchers → matchable}/or.rb +2 -2
  87. data/lib/mongoid/{matchers → matchable}/size.rb +1 -1
  88. data/lib/mongoid/matchable.rb +152 -0
  89. data/lib/mongoid/persistable/creatable.rb +188 -0
  90. data/lib/mongoid/persistable/deletable.rb +149 -0
  91. data/lib/mongoid/persistable/destroyable.rb +60 -0
  92. data/lib/mongoid/persistable/incrementable.rb +36 -0
  93. data/lib/mongoid/persistable/logical.rb +38 -0
  94. data/lib/mongoid/persistable/poppable.rb +39 -0
  95. data/lib/mongoid/persistable/pullable.rb +55 -0
  96. data/lib/mongoid/persistable/pushable.rb +62 -0
  97. data/lib/mongoid/persistable/renamable.rb +35 -0
  98. data/lib/mongoid/persistable/savable.rb +52 -0
  99. data/lib/mongoid/persistable/settable.rb +33 -0
  100. data/lib/mongoid/persistable/unsettable.rb +36 -0
  101. data/lib/mongoid/persistable/updatable.rb +152 -0
  102. data/lib/mongoid/persistable/upsertable.rb +55 -0
  103. data/lib/mongoid/persistable.rb +216 -0
  104. data/lib/mongoid/positional.rb +71 -0
  105. data/lib/mongoid/query_cache.rb +247 -0
  106. data/lib/mongoid/railtie.rb +32 -45
  107. data/lib/mongoid/railties/database.rake +9 -25
  108. data/lib/mongoid/relations/accessors.rb +13 -49
  109. data/lib/mongoid/relations/auto_save.rb +15 -36
  110. data/lib/mongoid/relations/binding.rb +1 -24
  111. data/lib/mongoid/relations/bindings/embedded/in.rb +1 -1
  112. data/lib/mongoid/relations/bindings/embedded/many.rb +1 -3
  113. data/lib/mongoid/relations/bindings/referenced/in.rb +3 -8
  114. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -1
  115. data/lib/mongoid/relations/builder.rb +1 -1
  116. data/lib/mongoid/relations/builders/nested_attributes/many.rb +10 -13
  117. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -5
  118. data/lib/mongoid/relations/builders/referenced/in.rb +1 -1
  119. data/lib/mongoid/relations/builders/referenced/many.rb +1 -2
  120. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +1 -2
  121. data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
  122. data/lib/mongoid/relations/builders.rb +2 -2
  123. data/lib/mongoid/relations/cascading.rb +3 -5
  124. data/lib/mongoid/relations/constraint.rb +1 -1
  125. data/lib/mongoid/relations/conversions.rb +1 -1
  126. data/lib/mongoid/relations/counter_cache.rb +39 -15
  127. data/lib/mongoid/relations/eager/base.rb +149 -0
  128. data/lib/mongoid/relations/eager/belongs_to.rb +31 -0
  129. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +47 -0
  130. data/lib/mongoid/relations/eager/has_many.rb +38 -0
  131. data/lib/mongoid/relations/eager/has_one.rb +30 -0
  132. data/lib/mongoid/relations/eager.rb +46 -0
  133. data/lib/mongoid/relations/embedded/batchable.rb +4 -5
  134. data/lib/mongoid/relations/embedded/in.rb +4 -4
  135. data/lib/mongoid/relations/embedded/many.rb +14 -32
  136. data/lib/mongoid/relations/embedded/one.rb +1 -1
  137. data/lib/mongoid/relations/macros.rb +3 -4
  138. data/lib/mongoid/relations/many.rb +30 -31
  139. data/lib/mongoid/relations/marshalable.rb +3 -3
  140. data/lib/mongoid/relations/metadata.rb +14 -79
  141. data/lib/mongoid/relations/nested_builder.rb +2 -2
  142. data/lib/mongoid/relations/options.rb +1 -0
  143. data/lib/mongoid/relations/polymorphic.rb +0 -1
  144. data/lib/mongoid/relations/proxy.rb +21 -41
  145. data/lib/mongoid/relations/referenced/in.rb +4 -20
  146. data/lib/mongoid/relations/referenced/many.rb +19 -32
  147. data/lib/mongoid/relations/referenced/many_to_many.rb +15 -38
  148. data/lib/mongoid/relations/referenced/one.rb +6 -25
  149. data/lib/mongoid/relations/synchronization.rb +3 -3
  150. data/lib/mongoid/relations/touchable.rb +34 -1
  151. data/lib/mongoid/relations.rb +11 -25
  152. data/lib/mongoid/{reloading.rb → reloadable.rb} +6 -4
  153. data/lib/mongoid/{scoping.rb → scopable.rb} +36 -36
  154. data/lib/mongoid/selectable.rb +59 -0
  155. data/lib/mongoid/{serialization.rb → serializable.rb} +11 -2
  156. data/lib/mongoid/sessions/factory.rb +2 -0
  157. data/lib/mongoid/sessions/options.rb +180 -0
  158. data/lib/mongoid/sessions/storage_options.rb +140 -0
  159. data/lib/mongoid/sessions/thread_options.rb +19 -0
  160. data/lib/mongoid/sessions/validators/storage.rb +16 -3
  161. data/lib/mongoid/sessions.rb +37 -345
  162. data/lib/mongoid/{sharding.rb → shardable.rb} +5 -1
  163. data/lib/mongoid/{state.rb → stateful.rb} +13 -1
  164. data/lib/mongoid/support/query_counter.rb +23 -0
  165. data/lib/mongoid/tasks/database.rake +31 -0
  166. data/lib/mongoid/tasks/database.rb +107 -0
  167. data/lib/mongoid/threaded/lifecycle.rb +0 -28
  168. data/lib/mongoid/threaded.rb +0 -157
  169. data/lib/mongoid/timestamps/updated/short.rb +2 -2
  170. data/lib/mongoid/{hierarchy.rb → traversable.rb} +9 -5
  171. data/lib/mongoid/{validations → validatable}/associated.rb +4 -2
  172. data/lib/mongoid/{validations → validatable}/format.rb +1 -1
  173. data/lib/mongoid/{validations → validatable}/length.rb +1 -1
  174. data/lib/mongoid/{validations → validatable}/localizable.rb +1 -1
  175. data/lib/mongoid/{validations → validatable}/macros.rb +4 -3
  176. data/lib/mongoid/{validations → validatable}/presence.rb +1 -1
  177. data/lib/mongoid/{validations → validatable}/queryable.rb +1 -2
  178. data/lib/mongoid/{validations → validatable}/uniqueness.rb +23 -19
  179. data/lib/mongoid/{validations.rb → validatable.rb} +23 -10
  180. data/lib/mongoid/version.rb +1 -1
  181. data/lib/mongoid.rb +10 -76
  182. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +13 -24
  183. data/lib/rails/generators/mongoid/model/model_generator.rb +0 -1
  184. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +0 -3
  185. data/lib/rails/generators/mongoid_generator.rb +3 -40
  186. data/lib/rails/mongoid.rb +0 -122
  187. data/lib/support/ruby_version.rb +1 -1
  188. data/spec/app/models/account.rb +2 -6
  189. data/spec/app/models/acolyte.rb +2 -1
  190. data/spec/app/models/actor.rb +0 -1
  191. data/spec/app/models/address.rb +8 -3
  192. data/spec/app/models/animal.rb +1 -1
  193. data/spec/app/models/appointment.rb +3 -3
  194. data/spec/app/models/article.rb +1 -4
  195. data/spec/app/models/audio.rb +5 -0
  196. data/spec/app/models/author.rb +0 -2
  197. data/spec/app/models/band.rb +3 -2
  198. data/spec/app/models/bar.rb +1 -0
  199. data/spec/app/models/book.rb +1 -0
  200. data/spec/app/models/building.rb +0 -2
  201. data/spec/app/models/building_address.rb +0 -2
  202. data/spec/app/models/bus.rb +1 -1
  203. data/spec/app/models/canvas.rb +1 -1
  204. data/spec/app/models/contractor.rb +0 -2
  205. data/spec/app/models/country_code.rb +1 -1
  206. data/spec/app/models/definition.rb +2 -2
  207. data/spec/app/models/dog.rb +1 -1
  208. data/spec/app/models/draft.rb +9 -0
  209. data/spec/app/models/dragon.rb +4 -0
  210. data/spec/app/models/drug.rb +1 -3
  211. data/spec/app/models/dungeon.rb +4 -0
  212. data/spec/app/models/edit.rb +5 -0
  213. data/spec/app/models/even.rb +7 -0
  214. data/spec/app/models/event.rb +1 -1
  215. data/spec/app/models/filesystem.rb +1 -0
  216. data/spec/app/models/fish.rb +0 -1
  217. data/spec/app/models/fruits.rb +6 -0
  218. data/spec/app/models/game.rb +0 -2
  219. data/spec/app/models/house.rb +1 -3
  220. data/spec/app/models/item.rb +1 -5
  221. data/spec/app/models/jar.rb +1 -1
  222. data/spec/app/models/label.rb +4 -4
  223. data/spec/app/models/line_item.rb +1 -1
  224. data/spec/app/models/login.rb +1 -1
  225. data/spec/app/models/message.rb +8 -0
  226. data/spec/app/models/movie.rb +1 -0
  227. data/spec/app/models/name.rb +3 -3
  228. data/spec/app/models/note.rb +3 -1
  229. data/spec/app/models/odd.rb +7 -0
  230. data/spec/app/models/oscar.rb +1 -1
  231. data/spec/app/models/parent_doc.rb +1 -1
  232. data/spec/app/models/person.rb +16 -10
  233. data/spec/app/models/phone.rb +1 -3
  234. data/spec/app/models/player.rb +3 -3
  235. data/spec/app/models/post.rb +5 -3
  236. data/spec/app/models/preference.rb +1 -1
  237. data/spec/app/models/quiz.rb +0 -3
  238. data/spec/app/models/record.rb +10 -5
  239. data/spec/app/models/registry.rb +1 -1
  240. data/spec/app/models/server.rb +1 -1
  241. data/spec/app/models/service.rb +3 -3
  242. data/spec/app/models/sound.rb +5 -0
  243. data/spec/app/models/symptom.rb +1 -1
  244. data/spec/app/models/template.rb +1 -1
  245. data/spec/app/models/title.rb +0 -1
  246. data/spec/app/models/track.rb +5 -5
  247. data/spec/app/models/tree.rb +3 -3
  248. data/spec/app/models/video.rb +1 -5
  249. data/spec/app/models/wiki_page.rb +2 -5
  250. data/spec/app/models/word.rb +3 -0
  251. data/spec/app/models/word_origin.rb +1 -1
  252. data/spec/config/mongoid.yml +7 -8
  253. data/spec/helpers.rb +18 -0
  254. data/spec/mongoid/atomic/modifiers_spec.rb +22 -22
  255. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +8 -49
  256. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +7 -49
  257. data/spec/mongoid/atomic/paths/root_spec.rb +3 -61
  258. data/spec/mongoid/atomic/paths_spec.rb +19 -19
  259. data/spec/mongoid/atomic_spec.rb +19 -19
  260. data/spec/mongoid/{nested_attributes_spec.rb → attributes/nested_spec.rb} +335 -448
  261. data/spec/mongoid/attributes/readonly_spec.rb +58 -18
  262. data/spec/mongoid/attributes_spec.rb +315 -436
  263. data/spec/mongoid/{dirty_spec.rb → changeable_spec.rb} +203 -153
  264. data/spec/mongoid/{components_spec.rb → composable_spec.rb} +3 -3
  265. data/spec/mongoid/config/environment_spec.rb +3 -3
  266. data/spec/mongoid/config/options_spec.rb +6 -6
  267. data/spec/mongoid/config_spec.rb +24 -48
  268. data/spec/mongoid/contextual/aggregable/memory_spec.rb +12 -12
  269. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +78 -38
  270. data/spec/mongoid/contextual/atomic_spec.rb +68 -58
  271. data/spec/mongoid/contextual/find_and_modify_spec.rb +14 -14
  272. data/spec/mongoid/contextual/geo_near_spec.rb +22 -22
  273. data/spec/mongoid/contextual/map_reduce_spec.rb +27 -27
  274. data/spec/mongoid/contextual/memory_spec.rb +151 -94
  275. data/spec/mongoid/contextual/mongo_spec.rb +238 -150
  276. data/spec/mongoid/contextual/none_spec.rb +127 -0
  277. data/spec/mongoid/contextual/text_search_spec.rb +209 -0
  278. data/spec/mongoid/copyable_spec.rb +56 -68
  279. data/spec/mongoid/criteria/findable_spec.rb +991 -0
  280. data/spec/mongoid/{criterion/inspection_spec.rb → criteria/inspectable_spec.rb} +5 -5
  281. data/spec/mongoid/{criterion → criteria}/marshalable_spec.rb +2 -2
  282. data/spec/mongoid/criteria/modifiable_spec.rb +1255 -0
  283. data/spec/mongoid/{criterion/scoping_spec.rb → criteria/scopable_spec.rb} +37 -37
  284. data/spec/mongoid/criteria_spec.rb +578 -2295
  285. data/spec/mongoid/document_spec.rb +166 -120
  286. data/spec/mongoid/equality_spec.rb +22 -22
  287. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +3 -3
  288. data/spec/mongoid/errors/callback_spec.rb +3 -3
  289. data/spec/mongoid/errors/delete_restriction_spec.rb +3 -3
  290. data/spec/mongoid/errors/document_not_destroyed_spec.rb +33 -0
  291. data/spec/mongoid/errors/document_not_found_spec.rb +11 -11
  292. data/spec/mongoid/errors/eager_load_spec.rb +3 -3
  293. data/spec/mongoid/errors/invalid_collection_spec.rb +3 -3
  294. data/spec/mongoid/errors/invalid_config_option_spec.rb +3 -3
  295. data/spec/mongoid/errors/invalid_field_option_spec.rb +3 -3
  296. data/spec/mongoid/errors/invalid_field_spec.rb +3 -3
  297. data/spec/mongoid/errors/invalid_find_spec.rb +3 -3
  298. data/spec/mongoid/errors/invalid_includes_spec.rb +3 -3
  299. data/spec/mongoid/errors/invalid_index_spec.rb +3 -3
  300. data/spec/mongoid/errors/invalid_options_spec.rb +3 -3
  301. data/spec/mongoid/errors/invalid_path_spec.rb +3 -3
  302. data/spec/mongoid/errors/invalid_scope_spec.rb +5 -5
  303. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -3
  304. data/spec/mongoid/errors/invalid_storage_options_spec.rb +3 -3
  305. data/spec/mongoid/errors/invalid_time_spec.rb +3 -3
  306. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -3
  307. data/spec/mongoid/errors/mixed_relations_spec.rb +3 -3
  308. data/spec/mongoid/errors/mixed_session_configuration_spec.rb +3 -3
  309. data/spec/mongoid/errors/mongoid_error_spec.rb +8 -8
  310. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +3 -3
  311. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  312. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +3 -3
  313. data/spec/mongoid/errors/no_metadata_spec.rb +3 -3
  314. data/spec/mongoid/errors/no_parent_spec.rb +3 -3
  315. data/spec/mongoid/errors/no_session_config_spec.rb +3 -3
  316. data/spec/mongoid/errors/no_session_database_spec.rb +3 -3
  317. data/spec/mongoid/errors/no_session_hosts_spec.rb +3 -3
  318. data/spec/mongoid/errors/no_sessions_config_spec.rb +3 -3
  319. data/spec/mongoid/errors/readonly_attribute_spec.rb +3 -3
  320. data/spec/mongoid/errors/readonly_document_spec.rb +29 -0
  321. data/spec/mongoid/errors/scope_overwrite_spec.rb +3 -3
  322. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -3
  323. data/spec/mongoid/errors/unknown_attribute_spec.rb +5 -5
  324. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -3
  325. data/spec/mongoid/errors/unsupported_javascript_spec.rb +3 -3
  326. data/spec/mongoid/errors/validations_spec.rb +7 -7
  327. data/spec/mongoid/extensions/array_spec.rb +61 -61
  328. data/spec/mongoid/extensions/big_decimal_spec.rb +11 -11
  329. data/spec/mongoid/extensions/binary_spec.rb +12 -12
  330. data/spec/mongoid/extensions/boolean_spec.rb +18 -18
  331. data/spec/mongoid/extensions/date_spec.rb +13 -13
  332. data/spec/mongoid/extensions/date_time_spec.rb +8 -8
  333. data/spec/mongoid/extensions/false_class_spec.rb +5 -5
  334. data/spec/mongoid/extensions/float_spec.rb +29 -15
  335. data/spec/mongoid/extensions/hash_spec.rb +29 -29
  336. data/spec/mongoid/extensions/integer_spec.rb +15 -15
  337. data/spec/mongoid/extensions/module_spec.rb +2 -2
  338. data/spec/mongoid/extensions/nil_class_spec.rb +1 -1
  339. data/spec/mongoid/extensions/object_id_spec.rb +134 -134
  340. data/spec/mongoid/extensions/object_spec.rb +26 -26
  341. data/spec/mongoid/extensions/range_spec.rb +61 -12
  342. data/spec/mongoid/extensions/regexp_spec.rb +4 -4
  343. data/spec/mongoid/extensions/set_spec.rb +4 -4
  344. data/spec/mongoid/extensions/string_spec.rb +35 -46
  345. data/spec/mongoid/extensions/symbol_spec.rb +9 -9
  346. data/spec/mongoid/extensions/time_spec.rb +49 -49
  347. data/spec/mongoid/extensions/time_with_zone_spec.rb +34 -34
  348. data/spec/mongoid/extensions/true_class_spec.rb +5 -5
  349. data/spec/mongoid/extensions_spec.rb +15 -0
  350. data/spec/mongoid/factory_spec.rb +15 -15
  351. data/spec/mongoid/fields/foreign_key_spec.rb +73 -66
  352. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +15 -15
  353. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +22 -22
  354. data/spec/mongoid/fields/localized_spec.rb +38 -23
  355. data/spec/mongoid/fields/standard_spec.rb +12 -12
  356. data/spec/mongoid/fields_spec.rb +263 -217
  357. data/spec/mongoid/{finders_spec.rb → findable_spec.rb} +127 -27
  358. data/spec/mongoid/indexable/specification_spec.rb +102 -0
  359. data/spec/mongoid/{indexes_spec.rb → indexable_spec.rb} +171 -51
  360. data/spec/mongoid/{inspection_spec.rb → inspectable_spec.rb} +6 -14
  361. data/spec/mongoid/{callbacks_spec.rb → interceptable_spec.rb} +117 -116
  362. data/spec/mongoid/log_subscriber_spec.rb +75 -0
  363. data/spec/mongoid/loggable_spec.rb +1 -1
  364. data/spec/mongoid/{matchers → matchable}/all_spec.rb +4 -4
  365. data/spec/mongoid/{matchers → matchable}/and_spec.rb +11 -11
  366. data/spec/mongoid/{matchers → matchable}/default_spec.rb +15 -15
  367. data/spec/mongoid/{matchers → matchable}/exists_spec.rb +5 -5
  368. data/spec/mongoid/{matchers → matchable}/gt_spec.rb +9 -8
  369. data/spec/mongoid/{matchers → matchable}/gte_spec.rb +7 -7
  370. data/spec/mongoid/matchable/in_spec.rb +49 -0
  371. data/spec/mongoid/{matchers → matchable}/lt_spec.rb +7 -7
  372. data/spec/mongoid/{matchers → matchable}/lte_spec.rb +7 -7
  373. data/spec/mongoid/matchable/ne_spec.rb +46 -0
  374. data/spec/mongoid/matchable/nin_spec.rb +48 -0
  375. data/spec/mongoid/{matchers → matchable}/or_spec.rb +6 -6
  376. data/spec/mongoid/{matchers → matchable}/size_spec.rb +3 -3
  377. data/spec/mongoid/{matchers_spec.rb → matchable_spec.rb} +41 -41
  378. data/spec/mongoid/persistable/creatable_spec.rb +512 -0
  379. data/spec/mongoid/persistable/deletable_spec.rb +218 -0
  380. data/spec/mongoid/persistable/destroyable_spec.rb +192 -0
  381. data/spec/mongoid/persistable/incrementable_spec.rb +173 -0
  382. data/spec/mongoid/persistable/logical_spec.rb +143 -0
  383. data/spec/mongoid/persistable/poppable_spec.rb +115 -0
  384. data/spec/mongoid/persistable/pullable_spec.rb +228 -0
  385. data/spec/mongoid/persistable/pushable_spec.rb +258 -0
  386. data/spec/mongoid/persistable/renamable_spec.rb +135 -0
  387. data/spec/mongoid/persistable/savable_spec.rb +461 -0
  388. data/spec/mongoid/persistable/settable_spec.rb +139 -0
  389. data/spec/mongoid/persistable/unsettable_spec.rb +155 -0
  390. data/spec/mongoid/persistable/updatable_spec.rb +558 -0
  391. data/spec/mongoid/persistable/upsertable_spec.rb +106 -0
  392. data/spec/mongoid/persistable_spec.rb +206 -0
  393. data/spec/mongoid/{atomic/positionable_spec.rb → positional_spec.rb} +9 -9
  394. data/spec/mongoid/query_cache_spec.rb +231 -0
  395. data/spec/mongoid/railties/document_spec.rb +2 -2
  396. data/spec/mongoid/relations/accessors_spec.rb +53 -145
  397. data/spec/mongoid/relations/auto_save_spec.rb +37 -17
  398. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +12 -12
  399. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +3 -3
  400. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +5 -5
  401. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +26 -26
  402. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +10 -10
  403. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +19 -19
  404. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +12 -12
  405. data/spec/mongoid/relations/builders/embedded/in_spec.rb +4 -4
  406. data/spec/mongoid/relations/builders/embedded/many_spec.rb +18 -18
  407. data/spec/mongoid/relations/builders/embedded/one_spec.rb +11 -11
  408. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +12 -13
  409. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +14 -14
  410. data/spec/mongoid/relations/builders/referenced/in_spec.rb +24 -35
  411. data/spec/mongoid/relations/builders/referenced/many_spec.rb +15 -15
  412. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +18 -18
  413. data/spec/mongoid/relations/builders/referenced/one_spec.rb +12 -25
  414. data/spec/mongoid/relations/builders_spec.rb +21 -21
  415. data/spec/mongoid/relations/cascading/delete_spec.rb +9 -9
  416. data/spec/mongoid/relations/cascading/destroy_spec.rb +6 -6
  417. data/spec/mongoid/relations/cascading/nullify_spec.rb +4 -4
  418. data/spec/mongoid/relations/cascading/restrict_spec.rb +7 -7
  419. data/spec/mongoid/relations/cascading_spec.rb +16 -16
  420. data/spec/mongoid/relations/constraint_spec.rb +8 -7
  421. data/spec/mongoid/relations/conversions_spec.rb +16 -14
  422. data/spec/mongoid/relations/counter_cache_spec.rb +85 -0
  423. data/spec/mongoid/relations/cyclic_spec.rb +18 -18
  424. data/spec/mongoid/relations/eager/belongs_to_spec.rb +154 -0
  425. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +117 -0
  426. data/spec/mongoid/relations/eager/has_many_spec.rb +207 -0
  427. data/spec/mongoid/relations/eager/has_one_spec.rb +163 -0
  428. data/spec/mongoid/relations/eager_spec.rb +228 -0
  429. data/spec/mongoid/relations/embedded/dirty_spec.rb +8 -8
  430. data/spec/mongoid/relations/embedded/in_spec.rb +56 -57
  431. data/spec/mongoid/relations/embedded/many_spec.rb +393 -372
  432. data/spec/mongoid/relations/embedded/one_spec.rb +108 -141
  433. data/spec/mongoid/relations/macros_spec.rb +108 -102
  434. data/spec/mongoid/relations/metadata_spec.rb +180 -255
  435. data/spec/mongoid/relations/options_spec.rb +1 -1
  436. data/spec/mongoid/relations/polymorphic_spec.rb +13 -17
  437. data/spec/mongoid/relations/proxy_spec.rb +2 -2
  438. data/spec/mongoid/relations/referenced/in_spec.rb +128 -303
  439. data/spec/mongoid/relations/referenced/many_spec.rb +434 -527
  440. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +352 -424
  441. data/spec/mongoid/relations/referenced/one_spec.rb +149 -264
  442. data/spec/mongoid/relations/reflections_spec.rb +6 -6
  443. data/spec/mongoid/relations/synchronization_spec.rb +46 -50
  444. data/spec/mongoid/relations/targets/enumerable_spec.rb +118 -118
  445. data/spec/mongoid/relations/touchable_spec.rb +333 -0
  446. data/spec/mongoid/relations_spec.rb +16 -15
  447. data/spec/mongoid/{reloading_spec.rb → reloadable_spec.rb} +20 -60
  448. data/spec/mongoid/{scoping_spec.rb → scopable_spec.rb} +89 -164
  449. data/spec/mongoid/selectable_spec.rb +134 -0
  450. data/spec/mongoid/{serialization_spec.rb → serializable_spec.rb} +129 -82
  451. data/spec/mongoid/sessions/factory_spec.rb +49 -28
  452. data/spec/mongoid/sessions/mongo_uri_spec.rb +7 -7
  453. data/spec/mongoid/sessions/options_spec.rb +107 -0
  454. data/spec/mongoid/sessions_spec.rb +289 -178
  455. data/spec/mongoid/{sharding_spec.rb → shardable_spec.rb} +8 -8
  456. data/spec/mongoid/{state_spec.rb → stateful_spec.rb} +36 -11
  457. data/spec/mongoid/tasks/database_rake_spec.rb +285 -0
  458. data/spec/mongoid/tasks/database_spec.rb +160 -0
  459. data/spec/mongoid/threaded_spec.rb +17 -70
  460. data/spec/mongoid/timestamps/created/short_spec.rb +6 -6
  461. data/spec/mongoid/timestamps/created_spec.rb +5 -5
  462. data/spec/mongoid/timestamps/timeless_spec.rb +6 -6
  463. data/spec/mongoid/timestamps/updated/short_spec.rb +11 -11
  464. data/spec/mongoid/timestamps/updated_spec.rb +9 -13
  465. data/spec/mongoid/timestamps_spec.rb +9 -13
  466. data/spec/mongoid/{hierarchy_spec.rb → traversable_spec.rb} +19 -19
  467. data/spec/mongoid/{validations → validatable}/associated_spec.rb +45 -22
  468. data/spec/mongoid/{validations → validatable}/format_spec.rb +6 -6
  469. data/spec/mongoid/{validations → validatable}/length_spec.rb +14 -14
  470. data/spec/mongoid/{validations → validatable}/numericality_spec.rb +1 -1
  471. data/spec/mongoid/{validations → validatable}/presence_spec.rb +37 -44
  472. data/spec/mongoid/{validations → validatable}/uniqueness_spec.rb +184 -192
  473. data/spec/mongoid/{validations_spec.rb → validatable_spec.rb} +28 -28
  474. data/spec/mongoid_spec.rb +8 -8
  475. data/spec/rails/mongoid_spec.rb +19 -335
  476. data/spec/spec_helper.rb +29 -13
  477. metadata +296 -283
  478. data/lib/mongoid/atomic/positionable.rb +0 -73
  479. data/lib/mongoid/components.rb +0 -92
  480. data/lib/mongoid/config/inflections.rb +0 -6
  481. data/lib/mongoid/contextual/eager.rb +0 -158
  482. data/lib/mongoid/errors/versioning_not_on_root.rb +0 -23
  483. data/lib/mongoid/identity_map.rb +0 -163
  484. data/lib/mongoid/json.rb +0 -16
  485. data/lib/mongoid/matchers/strategies.rb +0 -97
  486. data/lib/mongoid/matchers.rb +0 -32
  487. data/lib/mongoid/multi_parameter_attributes.rb +0 -105
  488. data/lib/mongoid/nested_attributes.rb +0 -78
  489. data/lib/mongoid/observer.rb +0 -192
  490. data/lib/mongoid/paranoia.rb +0 -136
  491. data/lib/mongoid/persistence/atomic/add_to_set.rb +0 -47
  492. data/lib/mongoid/persistence/atomic/bit.rb +0 -35
  493. data/lib/mongoid/persistence/atomic/inc.rb +0 -45
  494. data/lib/mongoid/persistence/atomic/operation.rb +0 -154
  495. data/lib/mongoid/persistence/atomic/pop.rb +0 -32
  496. data/lib/mongoid/persistence/atomic/pull.rb +0 -32
  497. data/lib/mongoid/persistence/atomic/pull_all.rb +0 -32
  498. data/lib/mongoid/persistence/atomic/push.rb +0 -25
  499. data/lib/mongoid/persistence/atomic/push_all.rb +0 -25
  500. data/lib/mongoid/persistence/atomic/rename.rb +0 -30
  501. data/lib/mongoid/persistence/atomic/sets.rb +0 -28
  502. data/lib/mongoid/persistence/atomic/unset.rb +0 -27
  503. data/lib/mongoid/persistence/atomic.rb +0 -231
  504. data/lib/mongoid/persistence/deletion.rb +0 -31
  505. data/lib/mongoid/persistence/insertion.rb +0 -38
  506. data/lib/mongoid/persistence/modification.rb +0 -35
  507. data/lib/mongoid/persistence/operations/embedded/insert.rb +0 -46
  508. data/lib/mongoid/persistence/operations/embedded/remove.rb +0 -43
  509. data/lib/mongoid/persistence/operations/insert.rb +0 -34
  510. data/lib/mongoid/persistence/operations/remove.rb +0 -33
  511. data/lib/mongoid/persistence/operations/update.rb +0 -59
  512. data/lib/mongoid/persistence/operations/upsert.rb +0 -28
  513. data/lib/mongoid/persistence/operations.rb +0 -214
  514. data/lib/mongoid/persistence/upsertion.rb +0 -31
  515. data/lib/mongoid/persistence.rb +0 -357
  516. data/lib/mongoid/unit_of_work.rb +0 -61
  517. data/lib/mongoid/versioning.rb +0 -217
  518. data/lib/rack/mongoid/middleware/identity_map.rb +0 -39
  519. data/lib/rack/mongoid.rb +0 -2
  520. data/lib/rails/generators/mongoid/observer/observer_generator.rb +0 -17
  521. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +0 -4
  522. data/spec/app/models/actor_observer.rb +0 -15
  523. data/spec/app/models/callback_recorder.rb +0 -25
  524. data/spec/app/models/paranoid_phone.rb +0 -25
  525. data/spec/app/models/paranoid_post.rb +0 -36
  526. data/spec/app/models/phone_observer.rb +0 -6
  527. data/spec/mongoid/attributes/processing_spec.rb +0 -149
  528. data/spec/mongoid/criterion/destructive_spec.rb +0 -101
  529. data/spec/mongoid/criterion/modifiable_spec.rb +0 -409
  530. data/spec/mongoid/criterion/modification_spec.rb +0 -402
  531. data/spec/mongoid/errors/versioning_not_on_root_spec.rb +0 -29
  532. data/spec/mongoid/identity_map_spec.rb +0 -564
  533. data/spec/mongoid/json_spec.rb +0 -33
  534. data/spec/mongoid/matchers/in_spec.rb +0 -25
  535. data/spec/mongoid/matchers/ne_spec.rb +0 -25
  536. data/spec/mongoid/matchers/nin_spec.rb +0 -25
  537. data/spec/mongoid/multi_parameter_attributes_spec.rb +0 -128
  538. data/spec/mongoid/observer_spec.rb +0 -290
  539. data/spec/mongoid/paranoia_spec.rb +0 -759
  540. data/spec/mongoid/persistence/atomic/add_to_set_spec.rb +0 -262
  541. data/spec/mongoid/persistence/atomic/bit_spec.rb +0 -88
  542. data/spec/mongoid/persistence/atomic/inc_spec.rb +0 -133
  543. data/spec/mongoid/persistence/atomic/pop_spec.rb +0 -111
  544. data/spec/mongoid/persistence/atomic/pull_all_spec.rb +0 -77
  545. data/spec/mongoid/persistence/atomic/pull_spec.rb +0 -80
  546. data/spec/mongoid/persistence/atomic/push_all_spec.rb +0 -77
  547. data/spec/mongoid/persistence/atomic/push_spec.rb +0 -77
  548. data/spec/mongoid/persistence/atomic/rename_spec.rb +0 -42
  549. data/spec/mongoid/persistence/atomic/sets_spec.rb +0 -154
  550. data/spec/mongoid/persistence/atomic/unset_spec.rb +0 -65
  551. data/spec/mongoid/persistence/atomic_spec.rb +0 -216
  552. data/spec/mongoid/persistence/operations/embedded/insert_spec.rb +0 -191
  553. data/spec/mongoid/persistence/operations/embedded/remove_spec.rb +0 -8
  554. data/spec/mongoid/persistence/operations/insert_spec.rb +0 -149
  555. data/spec/mongoid/persistence/operations/remove_spec.rb +0 -113
  556. data/spec/mongoid/persistence/operations/update_spec.rb +0 -141
  557. data/spec/mongoid/persistence/operations/upsert_spec.rb +0 -59
  558. data/spec/mongoid/persistence/operations_spec.rb +0 -313
  559. data/spec/mongoid/persistence_spec.rb +0 -2279
  560. data/spec/mongoid/unit_of_work_spec.rb +0 -196
  561. data/spec/mongoid/versioning_spec.rb +0 -540
  562. data/spec/rack/mongoid/middleware/identity_map_spec.rb +0 -72
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for $pull and $pullAll operations.
6
+ #
7
+ # @since 4.0.0
8
+ module Pullable
9
+ extend ActiveSupport::Concern
10
+
11
+ # Pull single values from the provided arrays.
12
+ #
13
+ # @example Pull a value from the array.
14
+ # document.pull(names: "Jeff", levels: 5)
15
+ #
16
+ # @note If duplicate values are found they will all be pulled.
17
+ #
18
+ # @param [ Hash ] pulls The field/value pull pairs.
19
+ #
20
+ # @return [ true, false ] If the operation succeeded.
21
+ #
22
+ # @since 4.0.0
23
+ def pull(pulls)
24
+ prepare_atomic_operation do |ops|
25
+ process_atomic_operations(pulls) do |field, value|
26
+ (send(field) || []).delete(value)
27
+ ops[atomic_attribute_name(field)] = value
28
+ end
29
+ { "$pull" => ops }
30
+ end
31
+ end
32
+
33
+ # Pull multiple values from the provided array fields.
34
+ #
35
+ # @example Pull values from the arrays.
36
+ # document.pull_all(names: [ "Jeff", "Bob" ], levels: [ 5, 6 ])
37
+ #
38
+ # @param [ Hash ] pulls The pull all operations.
39
+ #
40
+ # @return [ true, false ] If the operation succeeded.
41
+ #
42
+ # @since 4.0.0
43
+ def pull_all(pulls)
44
+ prepare_atomic_operation do |ops|
45
+ process_atomic_operations(pulls) do |field, value|
46
+ existing = send(field) || []
47
+ value.each{ |val| existing.delete(val) }
48
+ ops[atomic_attribute_name(field)] = value
49
+ end
50
+ { "$pullAll" => ops }
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Persistable
4
+
5
+ # Defines behaviour for $push and $addToSet operations.
6
+ #
7
+ # @since 4.0.0
8
+ module Pushable
9
+ extend ActiveSupport::Concern
10
+
11
+ # Add the single values to the arrays only if the value does not already
12
+ # exist in the array.
13
+ #
14
+ # @example Add the values to the sets.
15
+ # document.add_to_set(names: "James", aliases: "Bond")
16
+ #
17
+ # @param [ Hash ] adds The field/value pairs to add.
18
+ #
19
+ # @return [ true, false ] If the operation succeeded.
20
+ #
21
+ # @since 4.0.0
22
+ def add_to_set(adds)
23
+ prepare_atomic_operation do |ops|
24
+ process_atomic_operations(adds) do |field, value|
25
+ existing = send(field) || (attributes[field] ||= [])
26
+ values = [ value ].flatten(1)
27
+ values.each do |val|
28
+ existing.push(val) unless existing.include?(val)
29
+ end
30
+ ops[atomic_attribute_name(field)] = { "$each" => values }
31
+ end
32
+ { "$addToSet" => ops }
33
+ end
34
+ end
35
+
36
+ # Push a single value or multiple values onto arrays.
37
+ #
38
+ # @example Push a single value onto arrays.
39
+ # document.push(names: "James", aliases: "007")
40
+ #
41
+ # @example Push multiple values onto arrays.
42
+ # document.push(names: [ "James", "Bond" ])
43
+ #
44
+ # @param [ Hash ] pushes The $push operations.
45
+ #
46
+ # @return [ true, false ] If the operation succeeded.
47
+ #
48
+ # @since 4.0.0
49
+ def push(pushes)
50
+ prepare_atomic_operation do |ops|
51
+ process_atomic_operations(pushes) do |field, value|
52
+ existing = send(field) || (attributes[field] ||= [])
53
+ values = [ value ].flatten(1)
54
+ values.each{ |val| existing.push(val) }
55
+ ops[atomic_attribute_name(field)] = { "$each" => values }
56
+ end
57
+ { "$push" => ops }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -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
+ send("#{field}=", 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,152 @@
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) && invalid?(:update)
114
+ process_flagged_destroys
115
+ result = run_callbacks(:save) do
116
+ run_callbacks(:update) do
117
+ yield(self)
118
+ true
119
+ end
120
+ end
121
+ post_process_persist(result, options) and result
122
+ end
123
+
124
+ # Update the document in the database.
125
+ #
126
+ # @example Update an existing document.
127
+ # document.update
128
+ #
129
+ # @param [ Hash ] options Options to pass to update.
130
+ #
131
+ # @option options [ true, false ] :validate Whether or not to validate.
132
+ #
133
+ # @return [ true, false ] True if succeeded, false if not.
134
+ #
135
+ # @since 1.0.0
136
+ def update_document(options = {})
137
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
138
+ prepare_update(options) do
139
+ updates, conflicts = init_atomic_updates
140
+ unless updates.empty?
141
+ coll = _root.collection
142
+ selector = atomic_selector
143
+ coll.find(selector).update(positionally(selector, updates))
144
+ conflicts.each_pair do |key, value|
145
+ coll.find(selector).update(positionally(selector, { key => value }))
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ 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,216 @@
1
+ # encoding: utf-8
2
+ require "mongoid/persistable/creatable"
3
+ require "mongoid/persistable/deletable"
4
+ require "mongoid/persistable/destroyable"
5
+ require "mongoid/persistable/incrementable"
6
+ require "mongoid/persistable/logical"
7
+ require "mongoid/persistable/poppable"
8
+ require "mongoid/persistable/pullable"
9
+ require "mongoid/persistable/pushable"
10
+ require "mongoid/persistable/renamable"
11
+ require "mongoid/persistable/savable"
12
+ require "mongoid/persistable/settable"
13
+ require "mongoid/persistable/updatable"
14
+ require "mongoid/persistable/upsertable"
15
+ require "mongoid/persistable/unsettable"
16
+
17
+ module Mongoid
18
+
19
+ # Contains general behaviour for persistence operations.
20
+ #
21
+ # @since 2.0.0
22
+ module Persistable
23
+ extend ActiveSupport::Concern
24
+ include Creatable
25
+ include Deletable
26
+ include Destroyable
27
+ include Incrementable
28
+ include Logical
29
+ include Poppable
30
+ include Positional
31
+ include Pullable
32
+ include Pushable
33
+ include Renamable
34
+ include Savable
35
+ include Settable
36
+ include Updatable
37
+ include Upsertable
38
+ include Unsettable
39
+
40
+ # The atomic operations that deal with arrays or sets in the db.
41
+ #
42
+ # @since 4.0.0
43
+ LIST_OPERATIONS = [ "$addToSet", "$push", "$pull", "$pullAll" ].freeze
44
+
45
+ # Execute operations atomically (in a single database call) for everything
46
+ # that would happen inside the block.
47
+ #
48
+ # @example Execute the operations atomically.
49
+ # document.atomically do
50
+ # document.set(name: "Tool").inc(likes: 10)
51
+ # end
52
+ #
53
+ # @return [ true, false ] If the operation succeeded.
54
+ #
55
+ # @since 4.0.0
56
+ def atomically
57
+ begin
58
+ @atomic_updates_to_execute = {}
59
+ yield(self) if block_given?
60
+ persist_atomic_operations(@atomic_updates_to_execute)
61
+ true
62
+ ensure
63
+ @atomic_updates_to_execute = nil
64
+ end
65
+ end
66
+
67
+ # Raise an error if validation failed.
68
+ #
69
+ # @example Raise the validation error.
70
+ # Person.fail_due_to_validation!(person)
71
+ #
72
+ # @param [ Document ] document The document to fail.
73
+ #
74
+ # @raise [ Errors::Validations ] The validation error.
75
+ #
76
+ # @since 4.0.0
77
+ def fail_due_to_validation!
78
+ raise Errors::Validations.new(self)
79
+ end
80
+
81
+ # Raise an error if a callback failed.
82
+ #
83
+ # @example Raise the callback error.
84
+ # Person.fail_due_to_callback!(person, :create!)
85
+ #
86
+ # @param [ Document ] document The document to fail.
87
+ # @param [ Symbol ] method The method being called.
88
+ #
89
+ # @raise [ Errors::Callback ] The callback error.
90
+ #
91
+ # @since 4.0.0
92
+ def fail_due_to_callback!(method)
93
+ raise Errors::Callback.new(self.class, method)
94
+ end
95
+
96
+ private
97
+
98
+ # Are we executing an atomically block on the current document?
99
+ #
100
+ # @api private
101
+ #
102
+ # @example Are we executing atomically?
103
+ # document.executing_atomically?
104
+ #
105
+ # @return [ true, false ] If we are current executing atomically.
106
+ #
107
+ # @since 4.0.0
108
+ def executing_atomically?
109
+ !@atomic_updates_to_execute.nil?
110
+ end
111
+
112
+ # Post process the persistence operation.
113
+ #
114
+ # @api private
115
+ #
116
+ # @example Post process the persistence operation.
117
+ # document.post_process_persist(true)
118
+ #
119
+ # @param [ Object ] result The result of the operation.
120
+ # @param [ Hash ] options The options.
121
+ #
122
+ # @return [ true ] true.
123
+ #
124
+ # @since 4.0.0
125
+ def post_process_persist(result, options = {})
126
+ post_persist unless result == false
127
+ errors.clear unless performing_validations?(options)
128
+ true
129
+ end
130
+
131
+ # Prepare an atomic persistence operation. Yields an empty hash to be sent
132
+ # to the update.
133
+ #
134
+ # @api private
135
+ #
136
+ # @example Prepare the atomic operation.
137
+ # document.prepare_atomic_operation do |coll, selector, opts|
138
+ # ...
139
+ # end
140
+ #
141
+ # @return [ Object ] The result of the operation.
142
+ #
143
+ # @since 4.0.0
144
+ def prepare_atomic_operation
145
+ operations = yield({})
146
+ persist_or_delay_atomic_operation(operations)
147
+ self
148
+ end
149
+
150
+ # Process the atomic operations - this handles the common behaviour of
151
+ # iterating through each op, getting the aliased field name, and removing
152
+ # appropriate dirty changes.
153
+ #
154
+ # @api private
155
+ #
156
+ # @example Process the atomic operations.
157
+ # document.process_atomic_operations(pulls) do |field, value|
158
+ # ...
159
+ # end
160
+ #
161
+ # @param [ Hash ] operations The atomic operations.
162
+ #
163
+ # @return [ Hash ] The operations.
164
+ #
165
+ # @since 4.0.0
166
+ def process_atomic_operations(operations)
167
+ operations.each do |field, value|
168
+ unless attribute_writable?(field)
169
+ raise Errors::ReadonlyAttribute.new(field, value)
170
+ end
171
+ normalized = database_field_name(field)
172
+ yield(normalized, value)
173
+ remove_change(normalized)
174
+ end
175
+ end
176
+
177
+ # If we are in an atomically block, add the operations to the delayed group,
178
+ # otherwise persist immediately.
179
+ #
180
+ # @api private
181
+ #
182
+ # @example Persist immediately or delay the operations.
183
+ # document.persist_or_delay_atomic_operation(ops)
184
+ #
185
+ # @param [ Hash ] operation The operation.
186
+ #
187
+ # @since 4.0.0
188
+ def persist_or_delay_atomic_operation(operation)
189
+ if executing_atomically?
190
+ operation.each do |(name, hash)|
191
+ @atomic_updates_to_execute[name] ||= {}
192
+ @atomic_updates_to_execute[name].merge!(hash)
193
+ end
194
+ else
195
+ persist_atomic_operations(operation)
196
+ end
197
+ end
198
+
199
+ # Persist the atomic operations.
200
+ #
201
+ # @api private
202
+ #
203
+ # @example Persist the atomic operations.
204
+ # persist_atomic_operations(ops)
205
+ #
206
+ # @param [ Hash ] operations The atomic operations.
207
+ #
208
+ # @since 4.0.0
209
+ def persist_atomic_operations(operations)
210
+ if persisted?
211
+ selector = atomic_selector
212
+ _root.collection.find(selector).update(positionally(selector, operations))
213
+ end
214
+ end
215
+ end
216
+ end