mongoid 3.1.7 → 4.0.2

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