mongoid 2.4.9 → 3.0.0.rc

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 (351) hide show
  1. data/CHANGELOG.md +869 -8
  2. data/LICENSE +1 -1
  3. data/README.md +10 -11
  4. data/Rakefile +2 -17
  5. data/lib/config/locales/en.yml +441 -51
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic/paths/embedded/many.rb +6 -6
  8. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -5
  9. data/lib/mongoid/atomic/paths/embedded.rb +4 -5
  10. data/lib/mongoid/atomic/paths/root.rb +4 -5
  11. data/lib/mongoid/atomic.rb +16 -6
  12. data/lib/mongoid/attributes/processing.rb +14 -10
  13. data/lib/mongoid/attributes/readonly.rb +56 -0
  14. data/lib/mongoid/attributes.rb +95 -32
  15. data/lib/mongoid/callbacks.rb +100 -42
  16. data/lib/mongoid/collections/retry.rb +2 -3
  17. data/lib/mongoid/components.rb +10 -22
  18. data/lib/mongoid/config/environment.rb +4 -3
  19. data/lib/mongoid/config/inflections.rb +6 -0
  20. data/lib/mongoid/config/options.rb +1 -1
  21. data/lib/mongoid/config/validators/option.rb +25 -0
  22. data/lib/mongoid/config/validators/session.rb +140 -0
  23. data/lib/mongoid/config/validators.rb +3 -0
  24. data/lib/mongoid/config.rb +87 -233
  25. data/lib/mongoid/contextual/aggregable/memory.rb +98 -0
  26. data/lib/mongoid/contextual/aggregable/mongo.rb +181 -0
  27. data/lib/mongoid/contextual/atomic.rb +179 -0
  28. data/lib/mongoid/contextual/command.rb +43 -0
  29. data/lib/mongoid/contextual/find_and_modify.rb +66 -0
  30. data/lib/mongoid/contextual/map_reduce.rb +273 -0
  31. data/lib/mongoid/contextual/memory.rb +383 -0
  32. data/lib/mongoid/contextual/mongo.rb +543 -0
  33. data/lib/mongoid/contextual.rb +50 -0
  34. data/lib/mongoid/copyable.rb +2 -2
  35. data/lib/mongoid/criteria.rb +436 -248
  36. data/lib/mongoid/criterion/inspection.rb +14 -8
  37. data/lib/mongoid/criterion/scoping.rb +114 -44
  38. data/lib/mongoid/dirty.rb +152 -67
  39. data/lib/mongoid/document.rb +68 -49
  40. data/lib/mongoid/errors/ambiguous_relationship.rb +51 -0
  41. data/lib/mongoid/errors/callback.rb +5 -6
  42. data/lib/mongoid/errors/delete_restriction.rb +29 -0
  43. data/lib/mongoid/errors/document_not_found.rb +98 -17
  44. data/lib/mongoid/errors/eager_load.rb +3 -6
  45. data/lib/mongoid/errors/invalid_collection.rb +3 -3
  46. data/lib/mongoid/errors/invalid_config_option.rb +27 -0
  47. data/lib/mongoid/errors/invalid_database.rb +3 -3
  48. data/lib/mongoid/errors/invalid_field.rb +54 -8
  49. data/lib/mongoid/errors/invalid_field_option.rb +35 -0
  50. data/lib/mongoid/errors/invalid_find.rb +3 -3
  51. data/lib/mongoid/errors/invalid_index.rb +28 -0
  52. data/lib/mongoid/errors/invalid_options.rb +4 -4
  53. data/lib/mongoid/errors/invalid_scope.rb +24 -0
  54. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +38 -0
  55. data/lib/mongoid/errors/invalid_storage_options.rb +27 -0
  56. data/lib/mongoid/errors/invalid_time.rb +3 -6
  57. data/lib/mongoid/errors/inverse_not_found.rb +29 -0
  58. data/lib/mongoid/errors/mixed_relations.rb +4 -9
  59. data/lib/mongoid/errors/mixed_session_configuration.rb +28 -0
  60. data/lib/mongoid/errors/mongoid_error.rb +54 -3
  61. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +28 -0
  62. data/lib/mongoid/errors/no_default_session.rb +23 -0
  63. data/lib/mongoid/errors/no_environment.rb +3 -3
  64. data/lib/mongoid/errors/no_map_reduce_output.rb +24 -0
  65. data/lib/mongoid/errors/no_parent.rb +24 -0
  66. data/lib/mongoid/errors/no_session_config.rb +22 -0
  67. data/lib/mongoid/errors/no_session_database.rb +27 -0
  68. data/lib/mongoid/errors/no_session_hosts.rb +27 -0
  69. data/lib/mongoid/errors/no_sessions_config.rb +20 -0
  70. data/lib/mongoid/errors/readonly_attribute.rb +25 -0
  71. data/lib/mongoid/errors/scope_overwrite.rb +4 -4
  72. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +4 -4
  73. data/lib/mongoid/errors/unknown_attribute.rb +25 -0
  74. data/lib/mongoid/errors/unsaved_document.rb +4 -8
  75. data/lib/mongoid/errors/unsupported_javascript.rb +27 -0
  76. data/lib/mongoid/errors/unsupported_version.rb +4 -4
  77. data/lib/mongoid/errors/validations.rb +7 -6
  78. data/lib/mongoid/errors/versioning_not_on_root.rb +23 -0
  79. data/lib/mongoid/errors.rb +22 -1
  80. data/lib/mongoid/extensions/array.rb +127 -0
  81. data/lib/mongoid/extensions/big_decimal.rb +42 -0
  82. data/lib/mongoid/extensions/boolean.rb +24 -0
  83. data/lib/mongoid/extensions/date.rb +70 -0
  84. data/lib/mongoid/extensions/date_time.rb +68 -0
  85. data/lib/mongoid/extensions/false_class.rb +26 -0
  86. data/lib/mongoid/extensions/float.rb +44 -0
  87. data/lib/mongoid/extensions/hash.rb +91 -0
  88. data/lib/mongoid/extensions/integer.rb +54 -0
  89. data/lib/mongoid/extensions/module.rb +28 -0
  90. data/lib/mongoid/extensions/nil_class.rb +21 -0
  91. data/lib/mongoid/extensions/object.rb +188 -0
  92. data/lib/mongoid/extensions/object_id.rb +53 -0
  93. data/lib/mongoid/extensions/range.rb +55 -0
  94. data/lib/mongoid/extensions/regexp.rb +27 -0
  95. data/lib/mongoid/extensions/set.rb +55 -0
  96. data/lib/mongoid/extensions/string.rb +155 -0
  97. data/lib/mongoid/extensions/symbol.rb +54 -0
  98. data/lib/mongoid/extensions/time.rb +78 -0
  99. data/lib/mongoid/extensions/time_with_zone.rb +55 -0
  100. data/lib/mongoid/extensions/true_class.rb +26 -0
  101. data/lib/mongoid/extensions.rb +28 -76
  102. data/lib/mongoid/factory.rb +4 -4
  103. data/lib/mongoid/fields/foreign_key.rb +134 -0
  104. data/lib/mongoid/fields/localized.rb +73 -0
  105. data/lib/mongoid/fields/standard.rb +268 -0
  106. data/lib/mongoid/fields/validators/macro.rb +83 -0
  107. data/lib/mongoid/fields/validators.rb +2 -0
  108. data/lib/mongoid/fields.rb +129 -194
  109. data/lib/mongoid/finders.rb +42 -43
  110. data/lib/mongoid/hierarchy.rb +25 -14
  111. data/lib/mongoid/identity_map.rb +39 -12
  112. data/lib/mongoid/indexes/validators/options.rb +80 -0
  113. data/lib/mongoid/indexes.rb +66 -15
  114. data/lib/mongoid/inspection.rb +1 -1
  115. data/lib/mongoid/javascript.rb +1 -1
  116. data/lib/mongoid/json.rb +2 -2
  117. data/lib/mongoid/loggable.rb +69 -0
  118. data/lib/mongoid/matchers/all.rb +7 -8
  119. data/lib/mongoid/matchers/and.rb +3 -3
  120. data/lib/mongoid/matchers/default.rb +6 -4
  121. data/lib/mongoid/matchers/exists.rb +2 -2
  122. data/lib/mongoid/matchers/gt.rb +2 -2
  123. data/lib/mongoid/matchers/gte.rb +2 -2
  124. data/lib/mongoid/matchers/in.rb +3 -7
  125. data/lib/mongoid/matchers/lt.rb +2 -2
  126. data/lib/mongoid/matchers/lte.rb +2 -2
  127. data/lib/mongoid/matchers/ne.rb +2 -2
  128. data/lib/mongoid/matchers/nin.rb +2 -2
  129. data/lib/mongoid/matchers/or.rb +2 -2
  130. data/lib/mongoid/matchers/size.rb +2 -2
  131. data/lib/mongoid/matchers/strategies.rb +3 -3
  132. data/lib/mongoid/matchers.rb +1 -1
  133. data/lib/mongoid/multi_parameter_attributes.rb +8 -10
  134. data/lib/mongoid/nested_attributes.rb +17 -9
  135. data/lib/mongoid/observer.rb +1 -2
  136. data/lib/mongoid/paranoia.rb +13 -18
  137. data/lib/mongoid/persistence/atomic/add_to_set.rb +5 -9
  138. data/lib/mongoid/persistence/atomic/bit.rb +5 -7
  139. data/lib/mongoid/persistence/atomic/inc.rb +5 -7
  140. data/lib/mongoid/persistence/atomic/operation.rb +45 -6
  141. data/lib/mongoid/persistence/atomic/pop.rb +5 -7
  142. data/lib/mongoid/persistence/atomic/pull.rb +5 -7
  143. data/lib/mongoid/persistence/atomic/pull_all.rb +5 -7
  144. data/lib/mongoid/persistence/atomic/push.rb +4 -10
  145. data/lib/mongoid/persistence/atomic/push_all.rb +4 -10
  146. data/lib/mongoid/persistence/atomic/rename.rb +6 -7
  147. data/lib/mongoid/persistence/atomic/sets.rb +5 -7
  148. data/lib/mongoid/persistence/atomic/unset.rb +4 -5
  149. data/lib/mongoid/persistence/atomic.rb +2 -2
  150. data/lib/mongoid/persistence/deletion.rb +2 -2
  151. data/lib/mongoid/persistence/insertion.rb +10 -16
  152. data/lib/mongoid/persistence/modification.rb +5 -9
  153. data/lib/mongoid/persistence/operations/embedded/insert.rb +7 -6
  154. data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -5
  155. data/lib/mongoid/persistence/operations/insert.rb +4 -4
  156. data/lib/mongoid/persistence/operations/remove.rb +4 -4
  157. data/lib/mongoid/persistence/operations/update.rb +5 -5
  158. data/lib/mongoid/persistence/operations.rb +6 -19
  159. data/lib/mongoid/persistence.rb +64 -27
  160. data/lib/mongoid/railtie.rb +26 -11
  161. data/lib/mongoid/railties/database.rake +22 -108
  162. data/lib/mongoid/relations/accessors.rb +119 -19
  163. data/lib/mongoid/relations/auto_save.rb +59 -5
  164. data/lib/mongoid/relations/binding.rb +211 -2
  165. data/lib/mongoid/relations/bindings/embedded/in.rb +16 -22
  166. data/lib/mongoid/relations/bindings/embedded/many.rb +9 -50
  167. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -16
  168. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -57
  169. data/lib/mongoid/relations/bindings/referenced/many.rb +8 -20
  170. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -19
  171. data/lib/mongoid/relations/bindings/referenced/one.rb +10 -24
  172. data/lib/mongoid/relations/builder.rb +3 -3
  173. data/lib/mongoid/relations/builders/embedded/in.rb +5 -5
  174. data/lib/mongoid/relations/builders/embedded/many.rb +12 -12
  175. data/lib/mongoid/relations/builders/embedded/one.rb +6 -6
  176. data/lib/mongoid/relations/builders/nested_attributes/many.rb +8 -8
  177. data/lib/mongoid/relations/builders/nested_attributes/one.rb +4 -4
  178. data/lib/mongoid/relations/builders/referenced/in.rb +4 -4
  179. data/lib/mongoid/relations/builders/referenced/many.rb +5 -5
  180. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +7 -5
  181. data/lib/mongoid/relations/builders/referenced/one.rb +5 -5
  182. data/lib/mongoid/relations/builders.rb +19 -16
  183. data/lib/mongoid/relations/cascading/delete.rb +12 -4
  184. data/lib/mongoid/relations/cascading/destroy.rb +3 -3
  185. data/lib/mongoid/relations/cascading/nullify.rb +3 -3
  186. data/lib/mongoid/relations/cascading/restrict.rb +37 -0
  187. data/lib/mongoid/relations/cascading.rb +6 -4
  188. data/lib/mongoid/relations/constraint.rb +4 -3
  189. data/lib/mongoid/relations/conversions.rb +5 -6
  190. data/lib/mongoid/relations/cyclic.rb +7 -7
  191. data/lib/mongoid/relations/embedded/batchable.rb +346 -0
  192. data/lib/mongoid/relations/embedded/in.rb +23 -12
  193. data/lib/mongoid/relations/embedded/many.rb +99 -148
  194. data/lib/mongoid/relations/embedded/one.rb +25 -14
  195. data/lib/mongoid/relations/macros.rb +105 -60
  196. data/lib/mongoid/relations/many.rb +93 -14
  197. data/lib/mongoid/relations/metadata.rb +231 -45
  198. data/lib/mongoid/relations/nested_builder.rb +3 -5
  199. data/lib/mongoid/relations/one.rb +14 -2
  200. data/lib/mongoid/relations/options.rb +2 -2
  201. data/lib/mongoid/relations/polymorphic.rb +9 -9
  202. data/lib/mongoid/relations/proxy.rb +60 -31
  203. data/lib/mongoid/relations/referenced/in.rb +40 -15
  204. data/lib/mongoid/relations/referenced/many.rb +116 -122
  205. data/lib/mongoid/relations/referenced/many_to_many.rb +101 -46
  206. data/lib/mongoid/relations/referenced/one.rb +34 -13
  207. data/lib/mongoid/relations/reflections.rb +3 -3
  208. data/lib/mongoid/relations/synchronization.rb +19 -23
  209. data/lib/mongoid/relations/targets/enumerable.rb +86 -57
  210. data/lib/mongoid/relations/touchable.rb +32 -0
  211. data/lib/mongoid/relations.rb +6 -6
  212. data/lib/mongoid/reloading.rb +12 -14
  213. data/lib/mongoid/scoping.rb +329 -0
  214. data/lib/mongoid/serialization.rb +13 -30
  215. data/lib/mongoid/sessions/factory.rb +106 -0
  216. data/lib/mongoid/sessions/mongo_uri.rb +93 -0
  217. data/lib/mongoid/sessions/validators/storage.rb +49 -0
  218. data/lib/mongoid/sessions/validators.rb +2 -0
  219. data/lib/mongoid/sessions.rb +359 -0
  220. data/lib/mongoid/sharding.rb +6 -6
  221. data/lib/mongoid/state.rb +6 -7
  222. data/lib/mongoid/threaded/lifecycle.rb +21 -21
  223. data/lib/mongoid/threaded/sessions.rb +0 -0
  224. data/lib/mongoid/threaded.rb +167 -59
  225. data/lib/mongoid/timestamps/created.rb +8 -4
  226. data/lib/mongoid/timestamps/timeless.rb +6 -4
  227. data/lib/mongoid/timestamps/updated.rb +3 -3
  228. data/lib/mongoid/timestamps.rb +1 -1
  229. data/lib/mongoid/unit_of_work.rb +61 -0
  230. data/lib/mongoid/validations/associated.rb +2 -2
  231. data/lib/mongoid/validations/format.rb +2 -2
  232. data/lib/mongoid/validations/presence.rb +34 -4
  233. data/lib/mongoid/validations/uniqueness.rb +103 -25
  234. data/lib/mongoid/validations.rb +62 -20
  235. data/lib/mongoid/version.rb +2 -2
  236. data/lib/mongoid/versioning.rb +25 -26
  237. data/lib/mongoid.rb +24 -39
  238. data/lib/rack/mongoid/middleware/identity_map.rb +3 -3
  239. data/lib/rails/generators/mongoid/config/config_generator.rb +1 -1
  240. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +59 -19
  241. data/lib/rails/generators/mongoid/model/model_generator.rb +7 -7
  242. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +2 -2
  243. data/lib/rails/generators/mongoid/observer/observer_generator.rb +4 -4
  244. data/lib/rails/generators/mongoid_generator.rb +5 -5
  245. data/lib/rails/mongoid.rb +69 -25
  246. metadata +93 -155
  247. data/lib/config/locales/bg.yml +0 -61
  248. data/lib/config/locales/de.yml +0 -61
  249. data/lib/config/locales/en-GB.yml +0 -64
  250. data/lib/config/locales/es.yml +0 -59
  251. data/lib/config/locales/fr.yml +0 -62
  252. data/lib/config/locales/hi.yml +0 -53
  253. data/lib/config/locales/hu.yml +0 -64
  254. data/lib/config/locales/id.yml +0 -62
  255. data/lib/config/locales/it.yml +0 -59
  256. data/lib/config/locales/ja.yml +0 -57
  257. data/lib/config/locales/kr.yml +0 -54
  258. data/lib/config/locales/nl.yml +0 -61
  259. data/lib/config/locales/pl.yml +0 -59
  260. data/lib/config/locales/pt-BR.yml +0 -60
  261. data/lib/config/locales/pt.yml +0 -60
  262. data/lib/config/locales/ro.yml +0 -66
  263. data/lib/config/locales/ru.yml +0 -61
  264. data/lib/config/locales/sv.yml +0 -60
  265. data/lib/config/locales/vi.yml +0 -62
  266. data/lib/config/locales/zh-CN.yml +0 -53
  267. data/lib/mongoid/collection.rb +0 -157
  268. data/lib/mongoid/collections/master.rb +0 -45
  269. data/lib/mongoid/collections/operations.rb +0 -44
  270. data/lib/mongoid/collections.rb +0 -120
  271. data/lib/mongoid/config/database.rb +0 -181
  272. data/lib/mongoid/config/replset_database.rb +0 -80
  273. data/lib/mongoid/contexts/enumerable/sort.rb +0 -43
  274. data/lib/mongoid/contexts/enumerable.rb +0 -313
  275. data/lib/mongoid/contexts/mongo.rb +0 -485
  276. data/lib/mongoid/contexts.rb +0 -25
  277. data/lib/mongoid/criterion/builder.rb +0 -34
  278. data/lib/mongoid/criterion/complex.rb +0 -84
  279. data/lib/mongoid/criterion/creational.rb +0 -34
  280. data/lib/mongoid/criterion/exclusion.rb +0 -108
  281. data/lib/mongoid/criterion/inclusion.rb +0 -290
  282. data/lib/mongoid/criterion/optional.rb +0 -259
  283. data/lib/mongoid/criterion/selector.rb +0 -177
  284. data/lib/mongoid/cursor.rb +0 -88
  285. data/lib/mongoid/default_scope.rb +0 -36
  286. data/lib/mongoid/errors/invalid_type.rb +0 -25
  287. data/lib/mongoid/extensions/array/deep_copy.rb +0 -25
  288. data/lib/mongoid/extensions/array/deletion.rb +0 -29
  289. data/lib/mongoid/extensions/false_class/equality.rb +0 -26
  290. data/lib/mongoid/extensions/hash/criteria_helpers.rb +0 -47
  291. data/lib/mongoid/extensions/hash/deep_copy.rb +0 -25
  292. data/lib/mongoid/extensions/hash/scoping.rb +0 -25
  293. data/lib/mongoid/extensions/integer/checks.rb +0 -23
  294. data/lib/mongoid/extensions/nil/collectionization.rb +0 -23
  295. data/lib/mongoid/extensions/object/checks.rb +0 -29
  296. data/lib/mongoid/extensions/object/deep_copy.rb +0 -21
  297. data/lib/mongoid/extensions/object/reflections.rb +0 -48
  298. data/lib/mongoid/extensions/object/substitutable.rb +0 -15
  299. data/lib/mongoid/extensions/object/yoda.rb +0 -44
  300. data/lib/mongoid/extensions/object_id/conversions.rb +0 -60
  301. data/lib/mongoid/extensions/proc/scoping.rb +0 -25
  302. data/lib/mongoid/extensions/string/checks.rb +0 -36
  303. data/lib/mongoid/extensions/string/conversions.rb +0 -22
  304. data/lib/mongoid/extensions/string/inflections.rb +0 -118
  305. data/lib/mongoid/extensions/symbol/checks.rb +0 -23
  306. data/lib/mongoid/extensions/symbol/inflections.rb +0 -67
  307. data/lib/mongoid/extensions/true_class/equality.rb +0 -26
  308. data/lib/mongoid/extras.rb +0 -31
  309. data/lib/mongoid/fields/internal/array.rb +0 -76
  310. data/lib/mongoid/fields/internal/big_decimal.rb +0 -63
  311. data/lib/mongoid/fields/internal/bignum.rb +0 -10
  312. data/lib/mongoid/fields/internal/binary.rb +0 -11
  313. data/lib/mongoid/fields/internal/boolean.rb +0 -58
  314. data/lib/mongoid/fields/internal/date.rb +0 -51
  315. data/lib/mongoid/fields/internal/date_time.rb +0 -28
  316. data/lib/mongoid/fields/internal/false_class.rb +0 -10
  317. data/lib/mongoid/fields/internal/fixnum.rb +0 -10
  318. data/lib/mongoid/fields/internal/float.rb +0 -47
  319. data/lib/mongoid/fields/internal/foreign_keys/array.rb +0 -88
  320. data/lib/mongoid/fields/internal/foreign_keys/object.rb +0 -56
  321. data/lib/mongoid/fields/internal/hash.rb +0 -11
  322. data/lib/mongoid/fields/internal/integer.rb +0 -59
  323. data/lib/mongoid/fields/internal/localized.rb +0 -62
  324. data/lib/mongoid/fields/internal/nil_class.rb +0 -53
  325. data/lib/mongoid/fields/internal/object.rb +0 -11
  326. data/lib/mongoid/fields/internal/object_id.rb +0 -46
  327. data/lib/mongoid/fields/internal/range.rb +0 -61
  328. data/lib/mongoid/fields/internal/set.rb +0 -57
  329. data/lib/mongoid/fields/internal/string.rb +0 -42
  330. data/lib/mongoid/fields/internal/symbol.rb +0 -43
  331. data/lib/mongoid/fields/internal/time.rb +0 -23
  332. data/lib/mongoid/fields/internal/time_with_zone.rb +0 -23
  333. data/lib/mongoid/fields/internal/timekeeping.rb +0 -122
  334. data/lib/mongoid/fields/internal/true_class.rb +0 -10
  335. data/lib/mongoid/fields/mappings.rb +0 -42
  336. data/lib/mongoid/fields/serializable.rb +0 -270
  337. data/lib/mongoid/identity.rb +0 -92
  338. data/lib/mongoid/keys.rb +0 -144
  339. data/lib/mongoid/logger.rb +0 -45
  340. data/lib/mongoid/multi_database.rb +0 -31
  341. data/lib/mongoid/named_scope.rb +0 -166
  342. data/lib/mongoid/relations/embedded/atomic/operation.rb +0 -63
  343. data/lib/mongoid/relations/embedded/atomic/pull.rb +0 -65
  344. data/lib/mongoid/relations/embedded/atomic/push_all.rb +0 -59
  345. data/lib/mongoid/relations/embedded/atomic/set.rb +0 -61
  346. data/lib/mongoid/relations/embedded/atomic/unset.rb +0 -41
  347. data/lib/mongoid/relations/embedded/atomic.rb +0 -89
  348. data/lib/mongoid/relations/referenced/batch/insert.rb +0 -57
  349. data/lib/mongoid/relations/referenced/batch.rb +0 -73
  350. data/lib/mongoid/safety.rb +0 -105
  351. data/lib/mongoid/scope.rb +0 -31
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
- module Mongoid #:nodoc:
3
- module Persistence #:nodoc:
4
- module Operations #:nodoc:
2
+ module Mongoid
3
+ module Persistence
4
+ module Operations
5
5
 
6
6
  # Update is a persistence command responsible for taking a document that
7
7
  # has already been saved to the database and saving it, depending on
@@ -42,9 +42,9 @@ module Mongoid #:nodoc:
42
42
  def persist
43
43
  prepare do
44
44
  unless updates.empty?
45
- collection.update(selector, updates, options)
45
+ collection.find(selector).update(updates)
46
46
  conflicts.each_pair do |key, value|
47
- collection.update(selector, { key => value }, options)
47
+ collection.find(selector).update({ key => value })
48
48
  end
49
49
  end
50
50
  end
@@ -5,14 +5,14 @@ require "mongoid/persistence/operations/update"
5
5
  require "mongoid/persistence/operations/embedded/insert"
6
6
  require "mongoid/persistence/operations/embedded/remove"
7
7
 
8
- module Mongoid #:nodoc:
9
- module Persistence #:nodoc:
8
+ module Mongoid
9
+ module Persistence
10
10
 
11
11
  # Persistence operations include this module to get basic functionality
12
12
  # on initialization.
13
13
  module Operations
14
14
 
15
- attr_reader :conflicts, :document
15
+ attr_reader :conflicts, :document, :options
16
16
 
17
17
  # Get the collection we should be persisting to.
18
18
  #
@@ -80,19 +80,6 @@ module Mongoid #:nodoc:
80
80
  @notifying_parent ||= !@options.delete(:suppress)
81
81
  end
82
82
 
83
- # Get all the options that will be sent to the database. Right now this
84
- # is only safe mode opts.
85
- #
86
- # @example Get the options hash.
87
- # operation.options
88
- #
89
- # @return [ Hash ] The options for the database.
90
- #
91
- # @since 2.1.0
92
- def options
93
- Safety.merge_safety_options(@options)
94
- end
95
-
96
83
  # Get the parent of the provided document.
97
84
  #
98
85
  # @example Get the parent.
@@ -154,9 +141,9 @@ module Mongoid #:nodoc:
154
141
  #
155
142
  # @since 2.1.0
156
143
  def init_updates
157
- document.atomic_updates.tap do |updates|
158
- @conflicts = updates.delete(:conflicts) || {}
159
- end
144
+ updates = document.atomic_updates
145
+ @conflicts = updates.delete(:conflicts) || {}
146
+ updates
160
147
  end
161
148
 
162
149
  class << self
@@ -5,7 +5,7 @@ require "mongoid/persistence/insertion"
5
5
  require "mongoid/persistence/modification"
6
6
  require "mongoid/persistence/operations"
7
7
 
8
- module Mongoid #:nodoc:
8
+ module Mongoid
9
9
 
10
10
  # The persistence module is a mixin to provide database accessor methods for
11
11
  # the document. These correspond to the appropriate accessors on a
@@ -19,7 +19,7 @@ module Mongoid #:nodoc:
19
19
  extend ActiveSupport::Concern
20
20
  include Atomic
21
21
 
22
- # Remove the document from the datbase with callbacks.
22
+ # Remove the document from the database with callbacks.
23
23
  #
24
24
  # @example Destroy a document.
25
25
  # document.destroy
@@ -29,11 +29,11 @@ module Mongoid #:nodoc:
29
29
  # @return [ true, false ] True if successful, false if not.
30
30
  def destroy(options = {})
31
31
  self.flagged_for_destroy = true
32
- run_callbacks(:destroy) do
32
+ result = run_callbacks(:destroy) do
33
33
  remove(options)
34
- end.tap do
35
- self.flagged_for_destroy = false
36
34
  end
35
+ self.flagged_for_destroy = false
36
+ result
37
37
  end
38
38
 
39
39
  # Insert a new document into the database. Will return the document
@@ -49,7 +49,7 @@ module Mongoid #:nodoc:
49
49
  Operations.insert(self, options).persist
50
50
  end
51
51
 
52
- # Remove the document from the datbase.
52
+ # Remove the document from the database.
53
53
  #
54
54
  # @example Remove the document.
55
55
  # document.remove
@@ -79,7 +79,35 @@ module Mongoid #:nodoc:
79
79
  return true
80
80
  end
81
81
 
82
- # Update the document in the datbase.
82
+ # Touch the document, in effect updating it's updated_at timestamp and
83
+ # optionally the provided field to the current time. If any belongs_to
84
+ # relations exist with a touch option, they will be updated as well.
85
+ #
86
+ # @example Update the updated_at timestamp.
87
+ # document.touch
88
+ #
89
+ # @example Update the updated_at and provided timestamps.
90
+ # document.touch(:audited)
91
+ #
92
+ # @note This will not autobuild relations if those options are set.
93
+ #
94
+ # @param [ Symbol ] field The name of an additional field to update.
95
+ #
96
+ # @return [ true ] true.
97
+ #
98
+ # @since 3.0.0
99
+ def touch(field = nil)
100
+ current = Time.now
101
+ write_attribute(:updated_at, current) if fields["updated_at"]
102
+ write_attribute(field, current) if field
103
+ collection.find(atomic_selector).update(atomic_updates)
104
+ without_autobuild do
105
+ touchables.each { |name| send(name).try(:touch) }
106
+ end
107
+ move_changes and true
108
+ end
109
+
110
+ # Update the document in the database.
83
111
  #
84
112
  # @example Update an existing document.
85
113
  # document.update
@@ -100,15 +128,21 @@ module Mongoid #:nodoc:
100
128
  # @param [ Symbol, String ] name The name of the attribute.
101
129
  # @param [ Object ] value The new value of the attribute.a
102
130
  #
131
+ # @raise [ Errors::ReadonlyAttribute ] If the field cannot be changed due
132
+ # to being flagged as reaodnly.
133
+ #
103
134
  # @return [ true, false ] True if save was successfull, false if not.
104
135
  #
105
136
  # @since 2.0.0.rc.6
106
137
  def update_attribute(name, value)
138
+ unless attribute_writable?(name.to_s)
139
+ raise Errors::ReadonlyAttribute.new(name, value)
140
+ end
107
141
  write_attribute(name, value)
108
- save(:validate => false)
142
+ save(validate: false)
109
143
  end
110
144
 
111
- # Update the document attributes in the datbase.
145
+ # Update the document attributes in the database.
112
146
  #
113
147
  # @example Update the document's attributes
114
148
  # document.update_attributes(:title => "Sir")
@@ -132,12 +166,12 @@ module Mongoid #:nodoc:
132
166
  #
133
167
  # @return [ true, false ] True if validation passed.
134
168
  def update_attributes!(attributes = {}, options = {})
135
- update_attributes(attributes, options).tap do |result|
136
- unless result
137
- self.class.fail_validate!(self) if errors.any?
138
- self.class.fail_callback!(self, :update_attributes!)
139
- end
169
+ result = update_attributes(attributes, options)
170
+ unless result
171
+ self.class.fail_validate!(self) if errors.any?
172
+ self.class.fail_callback!(self, :update_attributes!)
140
173
  end
174
+ result
141
175
  end
142
176
 
143
177
  # Upsert the document - will perform an insert if the document is new, and
@@ -174,7 +208,9 @@ module Mongoid #:nodoc:
174
208
  # @return [ Document ] The newly created document.
175
209
  def create(attributes = {}, options = {}, &block)
176
210
  _creating do
177
- new(attributes, options, &block).tap { |doc| doc.save }
211
+ doc = new(attributes, options, &block)
212
+ doc.save
213
+ doc
178
214
  end
179
215
  end
180
216
 
@@ -193,10 +229,10 @@ module Mongoid #:nodoc:
193
229
  # @return [ Document ] The newly created document.
194
230
  def create!(attributes = {}, options = {}, &block)
195
231
  _creating do
196
- new(attributes, options, &block).tap do |doc|
197
- fail_validate!(doc) if doc.insert.errors.any?
198
- fail_callback!(doc, :create!) if doc.new?
199
- end
232
+ doc = new(attributes, options, &block)
233
+ fail_validate!(doc) if doc.insert.errors.any?
234
+ fail_callback!(doc, :create!) if doc.new_record?
235
+ doc
200
236
  end
201
237
  end
202
238
 
@@ -216,11 +252,12 @@ module Mongoid #:nodoc:
216
252
  def delete_all(conditions = nil)
217
253
  conds = conditions || {}
218
254
  selector = conds[:conditions] || conds
219
- selector.merge!(:_type => name) if hereditary?
220
- collection.find(selector).count.tap do
221
- collection.remove(selector, Safety.merge_safety_options)
222
- Threaded.clear_options!
223
- end
255
+ selector.merge!(_type: name) if hereditary?
256
+ coll = collection
257
+ deleted = coll.find(selector).count
258
+ coll.find(selector).remove_all
259
+ Threaded.clear_options!
260
+ deleted
224
261
  end
225
262
 
226
263
  # Delete all documents given the supplied conditions. If no conditions
@@ -239,9 +276,9 @@ module Mongoid #:nodoc:
239
276
  def destroy_all(conditions = nil)
240
277
  conds = conditions || {}
241
278
  documents = where(conds[:conditions] || conds)
242
- documents.count.tap do
243
- documents.each { |doc| doc.destroy }
244
- end
279
+ destroyed = documents.count
280
+ documents.each { |doc| doc.destroy }
281
+ destroyed
245
282
  end
246
283
 
247
284
  # Raise an error if validation failed.
@@ -1,14 +1,13 @@
1
1
  # encoding: utf-8
2
- require "singleton"
3
2
  require "mongoid"
4
3
  require "mongoid/config"
5
4
  require "mongoid/railties/document"
6
5
  require "rails"
7
6
  require "rails/mongoid"
8
7
 
9
- module Rails #:nodoc:
10
- module Mongoid #:nodoc:
11
- class Railtie < Rails::Railtie #:nodoc:
8
+ module Rails
9
+ module Mongoid
10
+ class Railtie < Rails::Railtie
12
11
 
13
12
  # Determine which generator to use. app_generators was introduced after
14
13
  # 3.0.0.
@@ -23,7 +22,7 @@ module Rails #:nodoc:
23
22
  config.respond_to?(:app_generators) ? :app_generators : :generators
24
23
  end
25
24
 
26
- # Maping of rescued exceptions to HTTP responses
25
+ # Mapping of rescued exceptions to HTTP responses
27
26
  #
28
27
  # @example
29
28
  # railtie.rescue_responses
@@ -38,7 +37,7 @@ module Rails #:nodoc:
38
37
  }
39
38
  end
40
39
 
41
- config.send(generator).orm :mongoid, :migration => false
40
+ config.send(generator).orm :mongoid, migration: false
42
41
 
43
42
  if config.action_dispatch.rescue_responses
44
43
  config.action_dispatch.rescue_responses.merge!(rescue_responses)
@@ -73,15 +72,22 @@ module Rails #:nodoc:
73
72
  # # - host: localhost
74
73
  # # port: 27019
75
74
  # allow_dynamic_fields: false
76
- # parameterize_keys: false
77
75
  # persist_in_safe_mode: false
78
76
  #
79
77
  initializer "setup database" do
80
78
  config_file = Rails.root.join("config", "mongoid.yml")
81
- # @todo: Durran: Remove extra check when #1291 complete.
82
- if config_file.file? &&
83
- YAML.load(ERB.new(File.read(config_file)).result)[Rails.env].values.flatten.any?
84
- ::Mongoid.load!(config_file)
79
+ if config_file.file?
80
+ begin
81
+ ::Mongoid.load!(config_file)
82
+ rescue ::Mongoid::Errors::NoSessionsConfig => e
83
+ handle_configuration_error(e)
84
+ rescue ::Mongoid::Errors::NoDefaultSession => e
85
+ handle_configuration_error(e)
86
+ rescue ::Mongoid::Errors::NoSessionDatabase => e
87
+ handle_configuration_error(e)
88
+ rescue ::Mongoid::Errors::NoSessionHosts => e
89
+ handle_configuration_error(e)
90
+ end
85
91
  end
86
92
  end
87
93
 
@@ -139,6 +145,15 @@ module Rails #:nodoc:
139
145
  end
140
146
  end
141
147
  end
148
+
149
+ # Rails runs all initializers first before getting into any generator
150
+ # code, so we have no way in the intitializer to know if we are
151
+ # generating a mongoid.yml. So instead of failing, we catch all the
152
+ # errors and print them out.
153
+ def handle_configuration_error(e)
154
+ puts "There is a configuration error with the current mongoid.yml."
155
+ puts e.message
156
+ end
142
157
  end
143
158
  end
144
159
  end
@@ -1,27 +1,27 @@
1
1
  namespace :db do
2
2
 
3
3
  unless Rake::Task.task_defined?("db:drop")
4
- desc 'Drops all the collections for the database for the current Rails.env'
4
+ desc "Drops all the collections for the database for the current Rails.env"
5
5
  task :drop => "mongoid:drop"
6
6
  end
7
7
 
8
8
  unless Rake::Task.task_defined?("db:seed")
9
- # if another ORM has defined db:seed, don't run it twice.
10
- desc 'Load the seed data from db/seeds.rb'
9
+ # if another ORM has defined db:seed, don"t run it twice.
10
+ desc "Load the seed data from db/seeds.rb"
11
11
  task :seed => :environment do
12
- seed_file = File.join(Rails.root, 'db', 'seeds.rb')
12
+ seed_file = File.join(Rails.root, "db", "seeds.rb")
13
13
  load(seed_file) if File.exist?(seed_file)
14
14
  end
15
15
  end
16
16
 
17
17
  unless Rake::Task.task_defined?("db:setup")
18
- desc 'Create the database, and initialize with the seed data'
19
- task :setup => [ 'db:create', 'db:mongoid:create_indexes', 'db:seed' ]
18
+ desc "Create the database, and initialize with the seed data"
19
+ task :setup => [ "db:create", "db:mongoid:create_indexes", "db:seed" ]
20
20
  end
21
21
 
22
22
  unless Rake::Task.task_defined?("db:reseed")
23
- desc 'Delete data and seed'
24
- task :reseed => [ 'db:drop', 'db:seed' ]
23
+ desc "Delete data and seed"
24
+ task :reseed => [ "db:drop", "db:seed" ]
25
25
  end
26
26
 
27
27
  unless Rake::Task.task_defined?("db:create")
@@ -56,26 +56,13 @@ namespace :db do
56
56
  task :create_indexes => "mongoid:create_indexes"
57
57
  end
58
58
 
59
+ unless Rake::Task.task_defined?("db:remove_indexes")
60
+ task :remove_indexes => "mongoid:remove_indexes"
61
+ end
62
+
59
63
  namespace :mongoid do
60
- # gets a list of the mongoid models defined in the app/models directory
61
- def get_mongoid_models
62
- documents = []
63
- Dir.glob("app/models/**/*.rb").sort.each do |file|
64
- model_path = file[0..-4].split('/')[2..-1]
65
- begin
66
- klass = model_path.map { |path| path.camelize }.join('::').constantize
67
- if klass.ancestors.include?(Mongoid::Document) && !klass.embedded
68
- documents << klass
69
- end
70
- rescue => e
71
- # Just for non-mongoid objects that dont have the embedded
72
- # attribute at the class level.
73
- end
74
- end
75
- documents
76
- end
77
64
 
78
- desc 'Create the indexes defined on your mongoid models'
65
+ desc "Create the indexes defined on your mongoid models"
79
66
  task :create_indexes => :environment do
80
67
  engines_models_paths = Rails.application.railties.engines.map do |engine|
81
68
  engine.paths["app/models"].expanded
@@ -88,95 +75,22 @@ namespace :db do
88
75
  end
89
76
  end
90
77
 
91
- def convert_ids(obj)
92
- if obj.is_a?(String) && obj =~ /^[a-f0-9]{24}$/
93
- BSON::ObjectId(obj)
94
- elsif obj.is_a?(Array)
95
- obj.map do |v|
96
- convert_ids(v)
97
- end
98
- elsif obj.is_a?(Hash)
99
- obj.each_pair do |k, v|
100
- obj[k] = convert_ids(v)
101
- end
102
- else
103
- obj
104
- end
105
- end
106
-
107
- def collection_names
108
- @collection_names ||= get_mongoid_models.map{ |d| d.collection.name }.uniq
109
- end
110
-
111
- desc "Convert string objectids in mongo database to ObjectID type"
112
- task :objectid_convert => :environment do
113
- collection_names.each do |collection_name|
114
- puts "Converting #{collection_name} to use ObjectIDs"
115
-
116
- # get old collection
117
- collection = Mongoid.master.collection(collection_name)
118
-
119
- # get new collection (a clean one)
120
- collection.db["#{collection_name}_new"].drop
121
- new_collection = collection.db["#{collection_name}_new"]
122
-
123
- # convert collection documents
124
- collection.find({}, :timeout => false, :sort => "_id") do |cursor|
125
- cursor.each do |doc|
126
- new_doc = convert_ids(doc)
127
- new_collection.insert(new_doc, :safe => true)
128
- end
129
- end
130
-
131
- puts "Done! Converted collection is in #{new_collection.name}\n\n"
132
- end
133
-
134
- # no errors. great! now rename _new to collection_name
135
- collection_names.each do |collection_name|
136
- collection = Mongoid.master.collection(collection_name)
137
- new_collection = collection.db["#{collection_name}_new"]
138
-
139
- # swap collection to _old
140
- puts "Moving #{collection.name} to #{collection_name}_old"
141
- collection.db["#{collection_name}_old"].drop
142
-
143
- begin
144
- collection.rename("#{collection_name}_old")
145
- rescue Exception => e
146
- puts "Unable to rename database #{collection_name} to #{collection_name}_old"
147
- puts "reason: #{e.message}\n\n"
148
- end
149
-
150
- # swap _new to collection
151
- puts "Moving #{new_collection.name} to #{collection_name}\n\n"
152
-
153
- begin
154
- new_collection.rename(collection_name)
155
- rescue Exception => e
156
- puts "Unable to rename database #{new_collection.name} to #{collection_name}"
157
- puts "reason: #{e.message}\n\n"
158
- end
78
+ desc "Remove the indexes defined on your mongoid models without questions!"
79
+ task :remove_indexes => :environment do
80
+ engines_models_paths = Rails.application.railties.engines.map do |engine|
81
+ engine.paths["app/models"].expanded
159
82
  end
83
+ root_models_paths = Rails.application.paths["app/models"]
84
+ models_paths = engines_models_paths.push(root_models_paths).flatten
160
85
 
161
- puts "DONE! Run `rake db:mongoid:cleanup_old_collections` to remove old collections"
162
- end
163
-
164
- desc "Clean up old collections backed up by objectid_convert"
165
- task :cleanup_old_collections => :environment do
166
- collection_names.each do |collection_name|
167
- collection = Mongoid.master.collection(collection_name)
168
- collection.db["#{collection.name}_old"].drop
86
+ models_paths.each do |path|
87
+ ::Rails::Mongoid.remove_indexes("#{path}/**/*.rb")
169
88
  end
170
89
  end
171
90
 
172
91
  desc "Drops the database for the current Rails.env"
173
92
  task :drop => :environment do
174
- Mongoid.master.collections.select {|c| c.name !~ /system/ }.each { |c| c.drop }
93
+ ::Mongoid::Sessions.default.drop
175
94
  end
176
-
177
- ########
178
- # TODO: lots more useful db tasks can be added here. stuff like copyDatabase, etc
179
- ########
180
95
  end
181
-
182
96
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
- module Mongoid # :nodoc:
3
- module Relations #:nodoc:
2
+ module Mongoid
3
+ module Relations
4
4
 
5
5
  # This module contains all the behaviour related to accessing relations
6
6
  # through the getters and setters, and how to delegate to builders to
@@ -12,7 +12,7 @@ module Mongoid # :nodoc:
12
12
  # document is nil, then sets the relation on this document.
13
13
  #
14
14
  # @example Build the relation.
15
- # person.build(:addresses, { :id => 1 }, metadata)
15
+ # person.__build__(:addresses, { :id => 1 }, metadata)
16
16
  #
17
17
  # @param [ String, Symbol ] name The name of the relation.
18
18
  # @param [ Hash, BSON::ObjectId ] object The id or attributes to use.
@@ -22,7 +22,7 @@ module Mongoid # :nodoc:
22
22
  # @return [ Proxy ] The relation.
23
23
  #
24
24
  # @since 2.0.0.rc.1
25
- def build(name, object, metadata)
25
+ def __build__(name, object, metadata)
26
26
  relation = create_relation(object, metadata)
27
27
  set_relation(name, relation)
28
28
  end
@@ -74,7 +74,64 @@ module Mongoid # :nodoc:
74
74
  instance_variable_set("@#{name}", relation)
75
75
  end
76
76
 
77
- module ClassMethods #:nodoc:
77
+ private
78
+
79
+ # Is the current code executing without autobuild functionality?
80
+ #
81
+ # @example Is autobuild disabled?
82
+ # document.without_autobuild?
83
+ #
84
+ # @return [ true, false ] If autobuild is disabled.
85
+ #
86
+ # @since 3.0.0
87
+ def without_autobuild?
88
+ Threaded.executing?(:without_autobuild)
89
+ end
90
+
91
+ # Yield to the block with autobuild functionality turned off.
92
+ #
93
+ # @example Execute without autobuild.
94
+ # document.without_autobuild do
95
+ # document.name
96
+ # end
97
+ #
98
+ # @return [ Object ] The result of the yield.
99
+ #
100
+ # @since 3.0.0
101
+ def without_autobuild
102
+ Threaded.begin("without_autobuild")
103
+ yield
104
+ ensure
105
+ Threaded.exit("without_autobuild")
106
+ end
107
+
108
+ module ClassMethods
109
+
110
+ # Adds the existence check for relations.
111
+ #
112
+ # @example Add the existence check.
113
+ # Person.existence_check(:name, meta)
114
+ #
115
+ # @example Check if a relation exists.
116
+ # person = Person.new
117
+ # person.has_game?
118
+ # person.game?
119
+ #
120
+ # @param [ String, Symbol ] name The name of the relation.
121
+ # @param [ Metadata ] The metadata.
122
+ #
123
+ # @return [ Class ] The model being set up.
124
+ #
125
+ # @since 3.0.0
126
+ def existence_check(name, metadata)
127
+ module_eval <<-END
128
+ def #{name}?
129
+ without_autobuild { !#{name}.blank? }
130
+ end
131
+ alias :has_#{name}? :#{name}?
132
+ END
133
+ self
134
+ end
78
135
 
79
136
  # Defines the getter for the relation. Nothing too special here: just
80
137
  # return the instance variable for the relation if it exists or build
@@ -90,22 +147,43 @@ module Mongoid # :nodoc:
90
147
  #
91
148
  # @since 2.0.0.rc.1
92
149
  def getter(name, metadata)
93
- tap do
94
- define_method(name) do |*args|
95
- reload, variable = args.first, "@#{name}"
96
- if instance_variable_defined?(variable) && !reload
97
- instance_variable_get(variable)
98
- else
99
- _building do
100
- _loading do
101
- build(name, attributes[metadata.key], metadata)
102
- end
103
- end
150
+ re_define_method(name) do |*args|
151
+ reload, variable = args.first, "@#{name}"
152
+ value = if instance_variable_defined?(variable) && !reload
153
+ instance_variable_get(variable)
154
+ else
155
+ _building do
156
+ _loading { __build__(name, attributes[metadata.key], metadata) }
104
157
  end
105
158
  end
159
+ if value.nil? && metadata.autobuilding? && !without_autobuild?
160
+ send("build_#{name}")
161
+ else
162
+ value
163
+ end
164
+ end
165
+ self
166
+ end
167
+
168
+ # Defines the getter for the ids of documents in the relation. Should
169
+ # be specify only for referenced many relations.
170
+ #
171
+ # @example Set up the ids getter for the relation.
172
+ # Person.ids_getter("addresses", metadata)
173
+ #
174
+ # @param [ String, Symbol ] name The name of the relation.
175
+ # @param [ Metadata] metadata The metadata for the relation.
176
+ #
177
+ # @return [ Class ] The class being set up.
178
+ def ids_getter(name, metadata)
179
+ ids_method = "#{name.to_s.singularize}_ids"
180
+ re_define_method(ids_method) do
181
+ send(name).only(:id).map(&:id)
106
182
  end
183
+ self
107
184
  end
108
185
 
186
+
109
187
  # Defines the setter for the relation. This does a few things based on
110
188
  # some conditions. If there is an existing association, a target
111
189
  # substitution will take place, otherwise a new relation will be
@@ -121,16 +199,38 @@ module Mongoid # :nodoc:
121
199
  #
122
200
  # @since 2.0.0.rc.1
123
201
  def setter(name, metadata)
124
- tap do
125
- define_method("#{name}=") do |object|
202
+ re_define_method("#{name}=") do |object|
203
+ without_autobuild do
126
204
  if relation_exists?(name) || metadata.many? ||
127
205
  (object.blank? && send(name))
128
206
  set_relation(name, send(name).substitute(object.substitutable))
129
207
  else
130
- build(name, object.substitutable, metadata)
208
+ __build__(name, object.substitutable, metadata)
131
209
  end
132
210
  end
133
211
  end
212
+ self
213
+ end
214
+
215
+ # Defines the setter method that allows you to set documents
216
+ # in this relation by their ids. The defined setter, finds
217
+ # documents with given ids and invokes regular relation setter
218
+ # with found documents. Ids setters should be defined only for
219
+ # referenced many relations.
220
+ #
221
+ # @example Set up the id_setter for the relation.
222
+ # Person.ids_setter("addesses", metadata)
223
+ #
224
+ # @param [ String, Symbol ] name The name of the relation.
225
+ # @param [ Metadata ] metadata The metadata for the relation.
226
+ #
227
+ # @return [ Class ] The class being set up.
228
+ def ids_setter(name, metadata)
229
+ ids_method = "#{name.to_s.singularize}_ids="
230
+ re_define_method(ids_method) do |ids|
231
+ send(metadata.setter, metadata.klass.find(ids))
232
+ end
233
+ self
134
234
  end
135
235
  end
136
236
  end