mongoid 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. data/README.rdoc +3 -1
  2. data/Rakefile +3 -2
  3. data/lib/config/locales/bg.yml +6 -0
  4. data/lib/config/locales/de.yml +6 -0
  5. data/lib/config/locales/en-GB.yml +48 -0
  6. data/lib/config/locales/en.yml +6 -3
  7. data/lib/config/locales/es.yml +6 -0
  8. data/lib/config/locales/fr.yml +6 -0
  9. data/lib/config/locales/hi.yml +39 -0
  10. data/lib/config/locales/hu.yml +13 -7
  11. data/lib/config/locales/id.yml +3 -0
  12. data/lib/config/locales/it.yml +7 -1
  13. data/lib/config/locales/ja.yml +4 -1
  14. data/lib/config/locales/kr.yml +9 -34
  15. data/lib/config/locales/nl.yml +6 -0
  16. data/lib/config/locales/pl.yml +6 -0
  17. data/lib/config/locales/pt-BR.yml +6 -0
  18. data/lib/config/locales/pt.yml +6 -0
  19. data/lib/config/locales/ro.yml +6 -0
  20. data/lib/config/locales/ru.yml +6 -0
  21. data/lib/config/locales/sv.yml +6 -0
  22. data/lib/config/locales/vi.yml +3 -0
  23. data/lib/config/locales/zh-CN.yml +6 -0
  24. data/lib/mongoid.rb +51 -45
  25. data/lib/mongoid/atomic.rb +145 -0
  26. data/lib/mongoid/atomic/modifiers.rb +109 -0
  27. data/lib/mongoid/atomic/paths.rb +3 -0
  28. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  29. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  30. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  31. data/lib/mongoid/atomic/paths/root.rb +40 -0
  32. data/lib/mongoid/attributes.rb +12 -23
  33. data/lib/mongoid/attributes/processing.rb +5 -5
  34. data/lib/mongoid/callbacks.rb +2 -0
  35. data/lib/mongoid/collection.rb +12 -59
  36. data/lib/mongoid/collections.rb +23 -20
  37. data/lib/mongoid/collections/master.rb +6 -4
  38. data/lib/mongoid/collections/operations.rb +1 -0
  39. data/lib/mongoid/collections/retry.rb +7 -0
  40. data/lib/mongoid/components.rb +2 -2
  41. data/lib/mongoid/config.rb +42 -55
  42. data/lib/mongoid/config/database.rb +6 -2
  43. data/lib/mongoid/config/replset_database.rb +7 -3
  44. data/lib/mongoid/contexts.rb +9 -3
  45. data/lib/mongoid/contexts/enumerable.rb +7 -3
  46. data/lib/mongoid/contexts/mongo.rb +139 -101
  47. data/lib/mongoid/criteria.rb +86 -69
  48. data/lib/mongoid/criterion/complex.rb +32 -5
  49. data/lib/mongoid/criterion/inclusion.rb +4 -2
  50. data/lib/mongoid/criterion/optional.rb +111 -86
  51. data/lib/mongoid/criterion/selector.rb +8 -4
  52. data/lib/mongoid/cursor.rb +27 -27
  53. data/lib/mongoid/dirty.rb +54 -214
  54. data/lib/mongoid/document.rb +37 -39
  55. data/lib/mongoid/errors/document_not_found.rb +3 -4
  56. data/lib/mongoid/errors/invalid_collection.rb +2 -3
  57. data/lib/mongoid/errors/invalid_database.rb +2 -3
  58. data/lib/mongoid/errors/invalid_field.rb +2 -3
  59. data/lib/mongoid/errors/invalid_options.rb +19 -7
  60. data/lib/mongoid/errors/invalid_type.rb +2 -3
  61. data/lib/mongoid/errors/mongoid_error.rb +5 -6
  62. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -3
  63. data/lib/mongoid/errors/unsupported_version.rb +2 -3
  64. data/lib/mongoid/errors/validations.rb +2 -3
  65. data/lib/mongoid/extensions.rb +8 -62
  66. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  67. data/lib/mongoid/extensions/false_class/equality.rb +14 -1
  68. data/lib/mongoid/extensions/hash/criteria_helpers.rb +21 -10
  69. data/lib/mongoid/extensions/hash/scoping.rb +14 -1
  70. data/lib/mongoid/extensions/nil/collectionization.rb +12 -1
  71. data/lib/mongoid/extensions/object/reflections.rb +33 -2
  72. data/lib/mongoid/extensions/object_id/conversions.rb +2 -36
  73. data/lib/mongoid/extensions/proc/scoping.rb +14 -1
  74. data/lib/mongoid/extensions/string/conversions.rb +4 -16
  75. data/lib/mongoid/extensions/string/inflections.rb +35 -14
  76. data/lib/mongoid/extensions/symbol/inflections.rb +38 -12
  77. data/lib/mongoid/extensions/true_class/equality.rb +14 -1
  78. data/lib/mongoid/extras.rb +11 -30
  79. data/lib/mongoid/factory.rb +1 -1
  80. data/lib/mongoid/fields.rb +121 -29
  81. data/lib/mongoid/fields/mappings.rb +36 -0
  82. data/lib/mongoid/fields/serializable.rb +131 -0
  83. data/lib/mongoid/fields/serializable/array.rb +64 -0
  84. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  85. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  86. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  87. data/lib/mongoid/fields/serializable/boolean.rb +44 -0
  88. data/lib/mongoid/fields/serializable/date.rb +51 -0
  89. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  90. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  91. data/lib/mongoid/fields/serializable/float.rb +33 -0
  92. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +56 -0
  93. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +43 -0
  94. data/lib/mongoid/fields/serializable/hash.rb +25 -0
  95. data/lib/mongoid/fields/serializable/integer.rb +33 -0
  96. data/lib/mongoid/fields/serializable/object.rb +11 -0
  97. data/lib/mongoid/fields/serializable/object_id.rb +32 -0
  98. data/lib/mongoid/fields/serializable/range.rb +42 -0
  99. data/lib/mongoid/fields/serializable/set.rb +42 -0
  100. data/lib/mongoid/fields/serializable/string.rb +28 -0
  101. data/lib/mongoid/fields/serializable/symbol.rb +28 -0
  102. data/lib/mongoid/fields/serializable/time.rb +12 -0
  103. data/lib/mongoid/fields/serializable/time_with_zone.rb +12 -0
  104. data/lib/mongoid/fields/serializable/timekeeping.rb +102 -0
  105. data/lib/mongoid/finders.rb +61 -37
  106. data/lib/mongoid/hierarchy.rb +43 -8
  107. data/lib/mongoid/identity_map.rb +106 -0
  108. data/lib/mongoid/indexes.rb +17 -1
  109. data/lib/mongoid/javascript.rb +2 -3
  110. data/lib/mongoid/keys.rb +10 -21
  111. data/lib/mongoid/logger.rb +22 -1
  112. data/lib/mongoid/matchers/all.rb +10 -0
  113. data/lib/mongoid/matchers/default.rb +1 -1
  114. data/lib/mongoid/matchers/exists.rb +10 -0
  115. data/lib/mongoid/matchers/gt.rb +10 -0
  116. data/lib/mongoid/matchers/gte.rb +10 -0
  117. data/lib/mongoid/matchers/in.rb +10 -0
  118. data/lib/mongoid/matchers/lt.rb +10 -0
  119. data/lib/mongoid/matchers/lte.rb +10 -0
  120. data/lib/mongoid/matchers/ne.rb +10 -0
  121. data/lib/mongoid/matchers/nin.rb +10 -0
  122. data/lib/mongoid/matchers/or.rb +7 -4
  123. data/lib/mongoid/matchers/size.rb +10 -0
  124. data/lib/mongoid/multi_database.rb +26 -6
  125. data/lib/mongoid/multi_parameter_attributes.rb +40 -17
  126. data/lib/mongoid/named_scope.rb +1 -2
  127. data/lib/mongoid/nested_attributes.rb +4 -1
  128. data/lib/mongoid/observer.rb +108 -5
  129. data/lib/mongoid/paranoia.rb +26 -26
  130. data/lib/mongoid/persistence.rb +15 -21
  131. data/lib/mongoid/persistence/atomic.rb +135 -0
  132. data/lib/mongoid/persistence/atomic/add_to_set.rb +11 -8
  133. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  134. data/lib/mongoid/persistence/atomic/inc.rb +9 -6
  135. data/lib/mongoid/persistence/atomic/operation.rb +48 -7
  136. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  137. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  138. data/lib/mongoid/persistence/atomic/pull_all.rb +10 -9
  139. data/lib/mongoid/persistence/atomic/push.rb +8 -5
  140. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  141. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  142. data/lib/mongoid/persistence/atomic/set.rb +30 -0
  143. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  144. data/lib/mongoid/persistence/deletion.rb +32 -0
  145. data/lib/mongoid/persistence/insertion.rb +41 -0
  146. data/lib/mongoid/persistence/modification.rb +37 -0
  147. data/lib/mongoid/persistence/operations.rb +214 -0
  148. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  149. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  150. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  151. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  152. data/lib/mongoid/persistence/operations/update.rb +53 -0
  153. data/lib/mongoid/railtie.rb +21 -33
  154. data/lib/mongoid/railties/database.rake +12 -12
  155. data/lib/mongoid/relations.rb +9 -5
  156. data/lib/mongoid/relations/accessors.rb +15 -36
  157. data/lib/mongoid/relations/auto_save.rb +2 -2
  158. data/lib/mongoid/relations/binding.rb +28 -1
  159. data/lib/mongoid/relations/bindings/embedded/in.rb +17 -30
  160. data/lib/mongoid/relations/bindings/embedded/many.rb +16 -21
  161. data/lib/mongoid/relations/bindings/embedded/one.rb +11 -16
  162. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -32
  163. data/lib/mongoid/relations/bindings/referenced/many.rb +19 -61
  164. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -63
  165. data/lib/mongoid/relations/bindings/referenced/one.rb +18 -26
  166. data/lib/mongoid/relations/builder.rb +4 -2
  167. data/lib/mongoid/relations/builders.rb +21 -2
  168. data/lib/mongoid/relations/builders/embedded/in.rb +5 -1
  169. data/lib/mongoid/relations/builders/embedded/many.rb +12 -4
  170. data/lib/mongoid/relations/builders/embedded/one.rb +5 -1
  171. data/lib/mongoid/relations/builders/nested_attributes/many.rb +2 -2
  172. data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
  173. data/lib/mongoid/relations/builders/referenced/in.rb +2 -5
  174. data/lib/mongoid/relations/builders/referenced/many.rb +2 -3
  175. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +14 -5
  176. data/lib/mongoid/relations/builders/referenced/one.rb +2 -3
  177. data/lib/mongoid/relations/embedded/atomic.rb +2 -2
  178. data/lib/mongoid/relations/embedded/in.rb +72 -41
  179. data/lib/mongoid/relations/embedded/many.rb +116 -120
  180. data/lib/mongoid/relations/embedded/one.rb +59 -41
  181. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  182. data/lib/mongoid/relations/macros.rb +28 -24
  183. data/lib/mongoid/relations/many.rb +10 -103
  184. data/lib/mongoid/relations/metadata.rb +335 -38
  185. data/lib/mongoid/relations/one.rb +7 -32
  186. data/lib/mongoid/relations/options.rb +47 -0
  187. data/lib/mongoid/relations/proxy.rb +29 -28
  188. data/lib/mongoid/relations/referenced/batch.rb +2 -3
  189. data/lib/mongoid/relations/referenced/in.rb +66 -53
  190. data/lib/mongoid/relations/referenced/many.rb +216 -143
  191. data/lib/mongoid/relations/referenced/many_to_many.rb +132 -163
  192. data/lib/mongoid/relations/referenced/one.rb +76 -58
  193. data/lib/mongoid/relations/synchronization.rb +113 -0
  194. data/lib/mongoid/relations/targets.rb +2 -0
  195. data/lib/mongoid/relations/targets/enumerable.rb +329 -0
  196. data/lib/mongoid/safety.rb +24 -156
  197. data/lib/mongoid/serialization.rb +21 -0
  198. data/lib/mongoid/state.rb +34 -0
  199. data/lib/mongoid/threaded.rb +175 -0
  200. data/lib/mongoid/timestamps/updated.rb +1 -1
  201. data/lib/mongoid/validations.rb +3 -7
  202. data/lib/mongoid/version.rb +1 -1
  203. data/lib/mongoid/versioning.rb +61 -7
  204. data/lib/rack/mongoid.rb +2 -0
  205. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  206. data/lib/rails/generators/mongoid/model/model_generator.rb +1 -1
  207. data/lib/rails/generators/mongoid/model/templates/{model.rb → model.rb.tt} +0 -0
  208. data/lib/rails/generators/mongoid/observer/observer_generator.rb +1 -1
  209. data/lib/rails/generators/mongoid/observer/templates/{observer.rb → observer.rb.tt} +0 -0
  210. data/lib/rails/mongoid.rb +17 -17
  211. metadata +136 -102
  212. data/lib/mongoid/atomicity.rb +0 -111
  213. data/lib/mongoid/collections/cyclic_iterator.rb +0 -34
  214. data/lib/mongoid/collections/slaves.rb +0 -61
  215. data/lib/mongoid/extensions/array/conversions.rb +0 -23
  216. data/lib/mongoid/extensions/array/parentization.rb +0 -13
  217. data/lib/mongoid/extensions/big_decimal/conversions.rb +0 -19
  218. data/lib/mongoid/extensions/binary/conversions.rb +0 -17
  219. data/lib/mongoid/extensions/boolean/conversions.rb +0 -27
  220. data/lib/mongoid/extensions/date/conversions.rb +0 -25
  221. data/lib/mongoid/extensions/datetime/conversions.rb +0 -12
  222. data/lib/mongoid/extensions/float/conversions.rb +0 -20
  223. data/lib/mongoid/extensions/hash/conversions.rb +0 -19
  224. data/lib/mongoid/extensions/integer/conversions.rb +0 -20
  225. data/lib/mongoid/extensions/object/conversions.rb +0 -25
  226. data/lib/mongoid/extensions/range/conversions.rb +0 -25
  227. data/lib/mongoid/extensions/set/conversions.rb +0 -20
  228. data/lib/mongoid/extensions/symbol/conversions.rb +0 -21
  229. data/lib/mongoid/extensions/time_conversions.rb +0 -38
  230. data/lib/mongoid/field.rb +0 -162
  231. data/lib/mongoid/paths.rb +0 -61
  232. data/lib/mongoid/persistence/command.rb +0 -71
  233. data/lib/mongoid/persistence/insert.rb +0 -53
  234. data/lib/mongoid/persistence/insert_embedded.rb +0 -43
  235. data/lib/mongoid/persistence/remove.rb +0 -44
  236. data/lib/mongoid/persistence/remove_all.rb +0 -40
  237. data/lib/mongoid/persistence/remove_embedded.rb +0 -48
  238. data/lib/mongoid/persistence/update.rb +0 -77
  239. data/lib/mongoid/safe.rb +0 -23
  240. data/lib/mongoid/validations/referenced.rb +0 -58
@@ -17,31 +17,22 @@ module Mongoid # :nodoc:
17
17
  # game.person.bind(:continue => true)
18
18
  # game.person = Person.new
19
19
  #
20
- # @param [ Hash ] options The binding options.
21
- #
22
- # @option options [ true, false ] :continue Continue binding the inverse.
23
- # @option options [ true, false ] :binding Are we in build mode?
24
- #
25
20
  # @since 2.0.0.rc.1
26
- def bind(options = {})
27
- inverse = metadata.inverse(target)
28
- base.send(metadata.foreign_key_setter, target.id)
29
- if metadata.inverse_type
30
- base.send(metadata.inverse_type_setter, target.class.name)
31
- end
32
- if inverse
33
- base.metadata = target.reflect_on_association(inverse)
34
- if options[:continue]
35
- if base.referenced_many?
36
- target.do_or_do_not(
37
- inverse, false, OPTIONS
38
- ).push(base, :binding => true, :continue => false)
39
- else
40
- target.do_or_do_not(
41
- metadata.inverse_setter(target),
42
- base,
43
- OPTIONS
44
- )
21
+ def bind
22
+ unless binding?
23
+ binding do
24
+ inverse = metadata.inverse(target)
25
+ base.send(metadata.foreign_key_setter, target.id)
26
+ if metadata.inverse_type
27
+ base.send(metadata.inverse_type_setter, target.class.model_name)
28
+ end
29
+ if inverse
30
+ base.metadata = metadata.inverse_metadata(target)
31
+ if base.referenced_many?
32
+ target.send(inverse).push(base)
33
+ else
34
+ target.do_or_do_not(metadata.inverse_setter(target), base)
35
+ end
45
36
  end
46
37
  end
47
38
  end
@@ -55,15 +46,23 @@ module Mongoid # :nodoc:
55
46
  # game.person.unbind(:continue => true)
56
47
  # game.person = nil
57
48
  #
58
- # @param [ Hash ] options The options to pass through.
59
- #
60
- # @option options [ true, false ] :continue Do we continue unbinding?
61
- #
62
49
  # @since 2.0.0.rc.1
63
- def unbind(options = {})
64
- base.do_or_do_not(metadata.foreign_key_setter, nil)
65
- if options[:continue]
66
- target.do_or_do_not(metadata.inverse_setter(target), nil, OPTIONS)
50
+ def unbind
51
+ unless binding?
52
+ binding do
53
+ inverse = metadata.inverse(target)
54
+ base.send(metadata.foreign_key_setter, nil)
55
+ if metadata.inverse_type
56
+ base.send(metadata.inverse_type_setter, nil)
57
+ end
58
+ if inverse
59
+ if base.referenced_many?
60
+ target.send(inverse).delete(base)
61
+ else
62
+ target.send(metadata.inverse_setter(target), nil)
63
+ end
64
+ end
65
+ end
67
66
  end
68
67
  end
69
68
  alias :unbind_one :unbind
@@ -7,26 +7,6 @@ module Mongoid # :nodoc:
7
7
  # Binding class for references_many relations.
8
8
  class Many < Binding
9
9
 
10
- # Binds the base object to the inverse of the relation. This is so we
11
- # are referenced to the actual objects themselves on both sides.
12
- #
13
- # This case sets the metadata on the inverse object as well as the
14
- # document itself.
15
- #
16
- # @example Bind all the documents.
17
- # person.posts.bind
18
- # person.posts = [ Post.new ]
19
- #
20
- # @param [ Hash ] options The binding options.
21
- #
22
- # @option options [ true, false ] :continue Continue binding the inverse.
23
- # @option options [ true, false ] :binding Are we in build mode?
24
- #
25
- # @since 2.0.0.rc.1
26
- def bind(options = {})
27
- target.each { |doc| bind_one(doc, options) }
28
- end
29
-
30
10
  # Binds a single document with the inverse relation. Used
31
11
  # specifically when appending to the proxy.
32
12
  #
@@ -34,59 +14,37 @@ module Mongoid # :nodoc:
34
14
  # person.posts.bind_one(post)
35
15
  #
36
16
  # @param [ Document ] doc The single document to bind.
37
- # @param [ Hash ] options The binding options.
38
- #
39
- # @option options [ true, false ] :continue Continue binding the inverse.
40
- # @option options [ true, false ] :binding Are we in build mode?
41
17
  #
42
18
  # @since 2.0.0.rc.1
43
- def bind_one(doc, options = {})
44
- if options[:continue]
45
- doc.do_or_do_not(metadata.foreign_key_setter, base.id)
46
- doc.do_or_do_not(
47
- metadata.inverse_setter,
48
- base,
49
- OPTIONS
50
- )
19
+ def bind_one(doc)
20
+ unless binding?
21
+ binding do
22
+ doc.send(metadata.foreign_key_setter, base.id)
23
+ if metadata.type
24
+ doc.send(metadata.type_setter, base.class.model_name)
25
+ end
26
+ doc.send(metadata.inverse_setter, base)
27
+ end
51
28
  end
52
29
  end
53
30
 
54
- # Unbinds the base object and the inverse, caused by setting the
55
- # reference to nil.
56
- #
57
- # @example Unbind the documents.
58
- # person.posts.unbind
59
- # person.posts = nil
60
- #
61
- # @param [ Hash ] options The binding options.
62
- #
63
- # @option options [ true, false ] :continue Continue binding the inverse.
64
- # @option options [ true, false ] :binding Are we in build mode?
65
- #
66
- # @since 2.0.0.rc.1
67
- def unbind(options = {})
68
- target.each { |doc| unbind_one(doc, options) }
69
- end
70
-
71
31
  # Unbind a single document.
72
32
  #
73
33
  # @example Unbind the document.
74
34
  # person.posts.unbind_one(document)
75
35
  #
76
- # @param [ Hash ] options The binding options.
77
- #
78
- # @option options [ true, false ] :continue Continue binding the inverse.
79
- # @option options [ true, false ] :binding Are we in build mode?
36
+ # @param [ Document ] document The document to unbind.
80
37
  #
81
38
  # @since 2.0.0.rc.1
82
- def unbind_one(doc, options = {})
83
- if options[:continue]
84
- doc.do_or_do_not(metadata.foreign_key_setter, nil)
85
- doc.do_or_do_not(
86
- metadata.inverse_setter,
87
- nil,
88
- OPTIONS
89
- )
39
+ def unbind_one(doc)
40
+ unless binding?
41
+ binding do
42
+ doc.send(metadata.foreign_key_setter, nil)
43
+ if metadata.type
44
+ doc.send(metadata.type_setter, nil)
45
+ end
46
+ doc.send(metadata.inverse_setter, nil)
47
+ end
90
48
  end
91
49
  end
92
50
  end
@@ -7,26 +7,6 @@ module Mongoid # :nodoc:
7
7
  # Binding class for all references_and_referenced_in_many relations.
8
8
  class ManyToMany < Binding
9
9
 
10
- # Binds the base object to the inverse of the relation. This is so we
11
- # are referenced to the actual objects themselves on both sides.
12
- #
13
- # This case sets the metadata on the inverse object as well as the
14
- # document itself.
15
- #
16
- # @example Bind all the documents.
17
- # person.preferences.bind
18
- # person.preferences = [ Preference.new ]
19
- #
20
- # @param [ Hash ] options The binding options.
21
- #
22
- # @option options [ true, false ] :continue Continue binding the inverse.
23
- # @option options [ true, false ] :binding Are we in build mode?
24
- #
25
- # @since 2.0.0.rc.1
26
- def bind(options = {})
27
- target.each { |doc| bind_one(doc, options) }
28
- end
29
-
30
10
  # Binds a single document with the inverse relation. Used
31
11
  # specifically when appending to the proxy.
32
12
  #
@@ -34,61 +14,33 @@ module Mongoid # :nodoc:
34
14
  # person.preferences.bind_one(preference)
35
15
  #
36
16
  # @param [ Document ] doc The single document to bind.
37
- # @param [ Hash ] options The binding options.
38
- #
39
- # @option options [ true, false ] :continue Continue binding the inverse.
40
- # @option options [ true, false ] :binding Are we in build mode?
41
17
  #
42
18
  # @since 2.0.0.rc.1
43
- def bind_one(doc, options = {})
44
- if options[:continue]
45
- inverse = metadata.inverse(target)
46
- if inverse
47
- doc.do_or_do_not(
48
- inverse,
49
- false,
50
- OPTIONS
51
- ).push(base, :binding => true, :continue => false)
19
+ def bind_one(doc)
20
+ unless binding?
21
+ binding do
22
+ inverse_keys = doc.do_or_do_not(metadata.inverse_foreign_key)
23
+ inverse_keys.push(base.id) if inverse_keys
24
+ base.synced[metadata.foreign_key] = true
25
+ doc.synced[metadata.inverse_foreign_key] = true
52
26
  end
53
27
  end
54
28
  end
55
29
 
56
- # Unbinds the base object and the inverse, caused by setting the
57
- # reference to nil.
58
- #
59
- # @example Unbind the documents.
60
- # person.preferences.unbind
61
- # person.preferences = nil
62
- #
63
- # @param [ Hash ] options The binding options.
64
- #
65
- # @option options [ true, false ] :continue Continue binding the inverse.
66
- # @option options [ true, false ] :binding Are we in build mode?
67
- #
68
- # @since 2.0.0.rc.1
69
- def unbind(options = {})
70
- target.each { |doc| unbind_one(doc, options) }
71
- end
72
-
73
30
  # Unbind a single document.
74
31
  #
75
32
  # @example Unbind the document.
76
33
  # person.preferences.unbind_one(document)
77
34
  #
78
- # @param [ Hash ] options The binding options.
79
- #
80
- # @option options [ true, false ] :continue Continue binding the inverse.
81
- # @option options [ true, false ] :binding Are we in build mode?
82
- #
83
35
  # @since 2.0.0.rc.1
84
- def unbind_one(doc, options = {})
85
- base.do_or_do_not(metadata.foreign_key).delete(doc.id)
86
- if options[:continue]
87
- inverse = metadata.inverse(target)
88
- if inverse
89
- doc.do_or_do_not(
90
- inverse, false, OPTIONS
91
- ).delete(base, :binding => true, :continue => false)
36
+ def unbind_one(doc)
37
+ unless binding?
38
+ binding do
39
+ base.send(metadata.foreign_key).delete_one(doc.id)
40
+ inverse_keys = doc.do_or_do_not(metadata.inverse_foreign_key)
41
+ inverse_keys.delete_one(base.id) if inverse_keys
42
+ base.synced[metadata.foreign_key] = true
43
+ doc.synced[metadata.inverse_foreign_key] = true
92
44
  end
93
45
  end
94
46
  end
@@ -17,20 +17,16 @@ module Mongoid # :nodoc:
17
17
  # person.game.bind(:continue => true)
18
18
  # person.game = Game.new
19
19
  #
20
- # @param [ Hash ] options The options to pass through.
21
- #
22
- # @option options [ true, false ] :continue Do we continue binding?
23
- # @option options [ true, false ] :binding Are we in build mode?
24
- #
25
20
  # @since 2.0.0.rc.1
26
- def bind(options = {})
27
- if options[:continue]
28
- target.do_or_do_not(metadata.foreign_key_setter, base.id)
29
- target.do_or_do_not(
30
- metadata.inverse_setter,
31
- base,
32
- OPTIONS
33
- )
21
+ def bind
22
+ unless binding?
23
+ binding do
24
+ target.send(metadata.foreign_key_setter, base.id)
25
+ target.send(metadata.inverse_setter, base)
26
+ if metadata.type
27
+ target.send(metadata.type_setter, base.class.model_name)
28
+ end
29
+ end
34
30
  end
35
31
  end
36
32
  alias :bind_one :bind
@@ -42,20 +38,16 @@ module Mongoid # :nodoc:
42
38
  # person.game.unbind(:continue => true)
43
39
  # person.game = nil
44
40
  #
45
- # @param [ Hash ] options The options to pass through.
46
- #
47
- # @option options [ true, false ] :continue Do we continue unbinding?
48
- # @option options [ true, false ] :binding Are we in build mode?
49
- #
50
41
  # @since 2.0.0.rc.1
51
- def unbind(options = {})
52
- if options[:continue]
53
- target.do_or_do_not(metadata.foreign_key_setter, nil)
54
- target.do_or_do_not(
55
- metadata.inverse_setter,
56
- nil,
57
- OPTIONS
58
- )
42
+ def unbind
43
+ unless binding?
44
+ binding do
45
+ target.send(metadata.foreign_key_setter, nil)
46
+ target.send(metadata.inverse_setter, nil)
47
+ if metadata.type
48
+ target.send(metadata.type_setter, nil)
49
+ end
50
+ end
59
51
  end
60
52
  end
61
53
  alias :unbind_one :unbind
@@ -7,7 +7,8 @@ module Mongoid # :nodoc:
7
7
  # supplied attributes hash.
8
8
  class Builder
9
9
 
10
- attr_reader :metadata, :object
10
+ attr_reader :metadata, :object, :loading
11
+
11
12
  # Instantiate the new builder for a relation.
12
13
  #
13
14
  # @example Create the builder.
@@ -18,8 +19,9 @@ module Mongoid # :nodoc:
18
19
  # id to query with.
19
20
  #
20
21
  # @since 2.0.0.rc.1
21
- def initialize(metadata, object)
22
+ def initialize(metadata, object, loading = false)
22
23
  @metadata, @object = metadata, object
24
+ @loading = loading
23
25
  end
24
26
 
25
27
  protected
@@ -32,6 +32,23 @@ module Mongoid # :nodoc:
32
32
  module Builders
33
33
  extend ActiveSupport::Concern
34
34
 
35
+ # Execute a block in building mode.
36
+ #
37
+ # @example Execute in building mode.
38
+ # building do
39
+ # relation.push(doc)
40
+ # end
41
+ #
42
+ # @return [ Object ] The return value of the block.
43
+ #
44
+ # @since 2.1.0
45
+ def building
46
+ Threaded.building = true
47
+ yield
48
+ ensure
49
+ Threaded.building = false
50
+ end
51
+
35
52
  module ClassMethods #:nodoc:
36
53
 
37
54
  # Defines a builder method for an embeds_one relation. This is
@@ -49,7 +66,9 @@ module Mongoid # :nodoc:
49
66
  tap do
50
67
  define_method("build_#{name}") do |*args|
51
68
  document = Factory.build(metadata.klass, args.first || {})
52
- send("#{name}=", document, :binding => true)
69
+ building do
70
+ send("#{name}=", document)
71
+ end
53
72
  end
54
73
  end
55
74
  end
@@ -69,7 +88,7 @@ module Mongoid # :nodoc:
69
88
  def creator(name)
70
89
  tap do
71
90
  define_method("create_#{name}") do |*args|
72
- send("build_#{name}", *args).tap(&:save)
91
+ send("build_#{name}", *args).tap { |doc| doc.save }
73
92
  end
74
93
  end
75
94
  end
@@ -16,7 +16,11 @@ module Mongoid # :nodoc:
16
16
  # @return [ Document ] A single document.
17
17
  def build(type = nil)
18
18
  return object unless object.is_a?(Hash)
19
- Mongoid::Factory.from_db(metadata.klass, object)
19
+ if loading
20
+ Mongoid::Factory.from_db(metadata.klass, object)
21
+ else
22
+ Mongoid::Factory.build(metadata.klass, object)
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -1,10 +1,13 @@
1
1
  # encoding: utf-8
2
+
3
+ require "mongoid/relations/embedded/sort"
4
+
2
5
  module Mongoid # :nodoc:
3
6
  module Relations #:nodoc:
4
7
  module Builders #:nodoc:
5
8
  module Embedded #:nodoc:
6
9
  class Many < Builder #:nodoc:
7
-
10
+ include Relations::Embedded::Sort
8
11
  # Builds the document out of the attributes using the provided
9
12
  # metadata on the relation. Instantiates through the factory in order
10
13
  # to make sure subclasses and allocation are used if fitting. This
@@ -19,10 +22,15 @@ module Mongoid # :nodoc:
19
22
  def build(type = nil)
20
23
  return [] if object.blank?
21
24
  return object if object.first.is_a?(Document)
22
- object.inject([]) do |documents, attrs|
23
- documents.tap do |docs|
24
- docs << Mongoid::Factory.from_db(metadata.klass, attrs)
25
+ [].tap do |docs|
26
+ object.each do |attrs|
27
+ if loading
28
+ docs << Mongoid::Factory.from_db(metadata.klass, attrs)
29
+ else
30
+ docs << Mongoid::Factory.build(metadata.klass, attrs)
31
+ end
25
32
  end
33
+ sort_documents!(docs, metadata) if metadata.order
26
34
  end
27
35
  end
28
36
  end