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
@@ -11,6 +11,9 @@ ro:
11
11
  invalid_type:
12
12
  Câmpul a fost definit ca şi un(o) %{klass}, dar valoarea
13
13
  recepţionată %{value} este de clasa %{other}.
14
+ invalid_options:
15
+ "Invalid option :%{invalid} provided to relation :%{name}. Valid options
16
+ are: %{valid}."
14
17
  unsupported_version:
15
18
  Versiunea MongoDB %{version} nu este suportată.
16
19
  Vă rugăm să folosiţi versiunea %{mongo_version}.
@@ -44,3 +47,6 @@ ro:
44
47
  unsaved_document:
45
48
  You cannot call create or create! through a relational association
46
49
  relation (%{document}) who's parent (%{base}) is not already saved.
50
+ mixed_relations:
51
+ Referencing a(n) %{embedded} document from the %{root} document via a
52
+ relational association is not allowed since the %{embedded} is embedded.
@@ -11,6 +11,9 @@ ru:
11
11
  invalid_type:
12
12
  Поле уже было определено в классе %{klass}, но получено как %{other}
13
13
  со значением %{value}.
14
+ invalid_options:
15
+ "Invalid option :%{invalid} provided to relation :%{name}. Valid options
16
+ are: %{valid}."
14
17
  unsupported_version:
15
18
  Версия MongoDB %{version} не поддерживается. Пожалуйста, обновитесь до
16
19
  версии %{mongo_version}.
@@ -39,3 +42,6 @@ ru:
39
42
  unsaved_document:
40
43
  Вызов методов create или create! запрещён у реляционной ассоциации
41
44
  (%{document}), у которой родитель (%{base}) не сохранён.
45
+ mixed_relations:
46
+ Referencing a(n) %{embedded} document from the %{root} document via a
47
+ relational association is not allowed since the %{embedded} is embedded.
@@ -11,6 +11,9 @@ sv:
11
11
  invalid_type:
12
12
  Fältet var definerat som %{klass}, men fick %{other} med
13
13
  värdet %{value}.
14
+ invalid_options:
15
+ "Invalid option :%{invalid} provided to relation :%{name}. Valid options
16
+ are: %{valid}."
14
17
  unsupported_version:
15
18
  MongoDB %{version} stöds ej, vänligen upgradera
16
19
  till %{mongo_version}.
@@ -38,3 +41,6 @@ sv:
38
41
  unsaved_document:
39
42
  You cannot call create or create! through a relational association
40
43
  relation (%{document}) who's parent (%{base}) is not already saved.
44
+ mixed_relations:
45
+ Referencing a(n) %{embedded} document from the %{root} document via a
46
+ relational association is not allowed since the %{embedded} is embedded.
@@ -11,6 +11,9 @@ vi:
11
11
  invalid_type:
12
12
  Trường được định nghĩa là một %{klass}, nhưng nhận được %{other} với
13
13
  giá trị %{value}.
14
+ invalid_options:
15
+ "Invalid option :%{invalid} provided to relation :%{name}. Valid options
16
+ are: %{valid}."
14
17
  unsupported_version:
15
18
  MongoDB %{version} không được hỗ trợ, xin vui lòng nâng cấp
16
19
  lên %{mongo_version}.
@@ -12,6 +12,9 @@ zh-CN:
12
12
  数据库应该是Mongo::DB,而不是%{name}.
13
13
  invalid_type:
14
14
  在类%{klass}中定义了字段,实际值是%{value}的%{other}.
15
+ invalid_options:
16
+ "Invalid option :%{invalid} provided to relation :%{name}. Valid options
17
+ are: %{valid}."
15
18
  unsupported_version:
16
19
  MongoDB %{version} 版本已过期,请升级到 %{mongo_version}.
17
20
  validations:
@@ -31,3 +34,6 @@ zh-CN:
31
34
  unsaved_document:
32
35
  You cannot call create or create! through a relational association
33
36
  relation (%{document}) who's parent (%{base}) is not already saved.
37
+ mixed_relations:
38
+ Referencing a(n) %{embedded} document from the %{root} document via a
39
+ relational association is not allowed since the %{embedded} is embedded.
@@ -22,27 +22,17 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  require "delegate"
24
24
  require "time"
25
- require "ostruct"
26
25
  require "active_support/core_ext"
27
26
  require 'active_support/json'
28
27
  require "active_support/inflector"
29
28
  require "active_support/time_with_zone"
30
29
  require "active_model"
31
- require "active_model/callbacks"
32
- require "active_model/conversion"
33
- require "active_model/errors"
34
- require "active_model/mass_assignment_security"
35
- require "active_model/naming"
36
- require "active_model/serialization"
37
- require "active_model/translation"
38
- require "active_model/validator"
39
- require "active_model/validations"
40
30
  require "mongo"
41
31
  require "mongoid/errors"
42
32
  require "mongoid/extensions"
43
- require "mongoid/safe"
44
33
  require "mongoid/relations"
45
- require "mongoid/atomicity"
34
+ require "mongoid/threaded"
35
+ require "mongoid/atomic"
46
36
  require "mongoid/attributes"
47
37
  require "mongoid/callbacks"
48
38
  require "mongoid/collection"
@@ -56,11 +46,11 @@ require "mongoid/default_scope"
56
46
  require "mongoid/dirty"
57
47
  require "mongoid/extras"
58
48
  require "mongoid/factory"
59
- require "mongoid/field"
60
49
  require "mongoid/fields"
61
50
  require "mongoid/finders"
62
51
  require "mongoid/hierarchy"
63
52
  require "mongoid/identity"
53
+ require "mongoid/identity_map"
64
54
  require "mongoid/indexes"
65
55
  require "mongoid/inspection"
66
56
  require "mongoid/javascript"
@@ -73,7 +63,6 @@ require "mongoid/multi_database"
73
63
  require "mongoid/named_scope"
74
64
  require "mongoid/nested_attributes"
75
65
  require "mongoid/observer"
76
- require "mongoid/paths"
77
66
  require "mongoid/persistence"
78
67
  require "mongoid/safety"
79
68
  require "mongoid/scope"
@@ -87,41 +76,61 @@ require "mongoid/components"
87
76
  require "mongoid/paranoia"
88
77
  require "mongoid/document"
89
78
 
90
- # add railtie
79
+ # If we are using Rails then we will include the Mongoid railtie. This has all
80
+ # the nifty initializers that Mongoid needs.
91
81
  if defined?(Rails)
92
82
  require "mongoid/railtie"
93
83
  end
94
84
 
85
+ # If we are using any Rack based application then we need the Mongoid rack
86
+ # middleware to ensure our app is running properly.
87
+ if defined?(Rack)
88
+ require "rack/mongoid"
89
+ end
90
+
95
91
  # add english load path by default
96
92
  I18n.load_path << File.join(File.dirname(__FILE__), "config", "locales", "en.yml")
97
93
 
98
94
  module Mongoid #:nodoc
95
+ extend self
99
96
 
100
- MONGODB_VERSION = "1.6.0"
97
+ MONGODB_VERSION = "1.8.0"
101
98
 
102
- class << self
99
+ # Sets the Mongoid configuration options. Best used by passing a block.
100
+ #
101
+ # @example Set up configuration options.
102
+ # Mongoid.configure do |config|
103
+ # name = "mongoid_test"
104
+ # host = "localhost"
105
+ # config.allow_dynamic_fields = false
106
+ # config.master = Mongo::Connection.new.db(name)
107
+ # end
108
+ #
109
+ # @return [ Config ] The configuration obejct.
110
+ #
111
+ # @since 1.0.0
112
+ def configure
113
+ block_given? ? yield(Config) : Config
114
+ end
115
+ alias :config :configure
103
116
 
104
- # Sets the Mongoid configuration options. Best used by passing a block.
105
- #
106
- # @example Set up configuration options.
107
- #
108
- # Mongoid.configure do |config|
109
- # name = "mongoid_test"
110
- # host = "localhost"
111
- # config.allow_dynamic_fields = false
112
- # config.master = Mongo::Connection.new.db(name)
113
- # config.slaves = [
114
- # Mongo::Connection.new(host, 27018, :slave_ok => true).db(name),
115
- # Mongo::Connection.new(host, 27019, :slave_ok => true).db(name)
116
- # ]
117
- # end
118
- #
119
- # @return [ Config ] The configuration obejct.
120
- def configure
121
- config = Mongoid::Config
122
- block_given? ? yield(config) : config
117
+ # We can process a unit of work in Mongoid and have the identity map
118
+ # automatically clear itself out after the work is complete.
119
+ #
120
+ # @example Process a unit of work.
121
+ # Mongoid.unit_of_work do
122
+ # Person.create(:title => "Sir")
123
+ # end
124
+ #
125
+ # @return [ Object ] The result of the block.
126
+ #
127
+ # @since 2.1.0
128
+ def unit_of_work
129
+ begin
130
+ yield if block_given?
131
+ ensure
132
+ IdentityMap.clear
123
133
  end
124
- alias :config :configure
125
134
  end
126
135
 
127
136
  # Take all the public instance methods from the Config singleton and allow
@@ -129,12 +138,9 @@ module Mongoid #:nodoc
129
138
  #
130
139
  # @example Delegate the configuration methods.
131
140
  # Mongoid.database = Mongo::Connection.new.db("test")
132
- (Mongoid::Config.public_instance_methods(false) +
133
- ActiveModel::Observing::ClassMethods.public_instance_methods(false)).each do |name|
134
- (class << self; self; end).class_eval <<-EOT
135
- def #{name}(*args)
136
- configure.send("#{name}", *args)
137
- end
138
- EOT
139
- end
141
+ #
142
+ # @since 1.0.0
143
+ delegate *(Config.public_instance_methods(false) +
144
+ ActiveModel::Observing::ClassMethods.public_instance_methods(false) <<
145
+ { :to => Config })
140
146
  end
@@ -0,0 +1,145 @@
1
+ # encoding: utf-8
2
+ require "mongoid/atomic/modifiers"
3
+ require "mongoid/atomic/paths"
4
+
5
+ module Mongoid #:nodoc:
6
+
7
+ # This module contains the logic for supporting atomic operations against the
8
+ # database.
9
+ module Atomic
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+
14
+ # When MongoDB finally fully implements the positional operator, we can
15
+ # get rid of all indexing related code in Mongoid.
16
+ attr_accessor :_index
17
+ end
18
+
19
+ # Get all the atomic updates that need to happen for the current
20
+ # +Document+. This includes all changes that need to happen in the
21
+ # entire hierarchy that exists below where the save call was made.
22
+ #
23
+ # @note MongoDB does not allow "conflicting modifications" to be
24
+ # performed in a single operation. Conflicting modifications are
25
+ # detected by the 'haveConflictingMod' function in MongoDB.
26
+ # Examination of the code suggests that two modifications (a $set
27
+ # and a $pushAll, for example) conflict if:
28
+ # (1) the key paths being modified are equal.
29
+ # (2) one key path is a prefix of the other.
30
+ # So a $set of 'addresses.0.street' will conflict with a $pushAll
31
+ # to 'addresses', and we will need to split our update into two
32
+ # pieces. We do not, however, attempt to match MongoDB's logic
33
+ # exactly. Instead, we assume that two updates conflict if the
34
+ # first component of the two key paths matches.
35
+ #
36
+ # @example Get the updates that need to occur.
37
+ # person.atomic_updates(children)
38
+ #
39
+ # @return [ Hash ] The updates and their modifiers.
40
+ #
41
+ # @since 2.1.0
42
+ def atomic_updates
43
+ Modifiers.new.tap do |mods|
44
+ mods.set(atomic_sets)
45
+ _children.each do |child|
46
+ mods.set(child.atomic_sets)
47
+ mods.push(child.atomic_pushes)
48
+ end
49
+ end
50
+ end
51
+ alias :_updates :atomic_updates
52
+
53
+ # Get the removal modifier for the document. Will be nil on root
54
+ # documents, $unset on embeds_one, $set on embeds_many.
55
+ #
56
+ # @example Get the removal operator.
57
+ # name.remover
58
+ #
59
+ # @return [ String ] The pull or unset operation.
60
+ def atomic_delete_modifier
61
+ atomic_paths.delete_modifier
62
+ end
63
+
64
+ # Get the insertion modifier for the document. Will be nil on root
65
+ # documents, $set on embeds_one, $push on embeds_many.
66
+ #
67
+ # @example Get the insert operation.
68
+ # name.inserter
69
+ #
70
+ # @return [ String ] The pull or set operator.
71
+ def atomic_insert_modifier
72
+ atomic_paths.insert_modifier
73
+ end
74
+
75
+ # Return the path to this +Document+ in JSON notation, used for atomic
76
+ # updates via $set in MongoDB.
77
+ #
78
+ # @example Get the path to this document.
79
+ # address.path
80
+ #
81
+ # @return [ String ] The path to the document in the database.
82
+ def atomic_path
83
+ atomic_paths.path
84
+ end
85
+
86
+ # Returns the positional operator of this document for modification.
87
+ #
88
+ # @example Get the positional operator.
89
+ # address.position
90
+ #
91
+ # @return [ String ] The positional operator with indexes.
92
+ def atomic_position
93
+ atomic_paths.position
94
+ end
95
+
96
+ # Get all the push attributes that need to occur.
97
+ #
98
+ # @example Get the pushes.
99
+ # person._pushes
100
+ #
101
+ # @return [ Hash ] The $pushAll operations.
102
+ #
103
+ # @since 2.1.0
104
+ def atomic_pushes
105
+ pushable? ? { atomic_path => as_document } : {}
106
+ end
107
+
108
+ # Return the selector for this document to be matched exactly for use
109
+ # with MongoDB's $ operator.
110
+ #
111
+ # @example Get the selector.
112
+ # address.selector
113
+ #
114
+ # @return [ String ] The exact selector for this document.
115
+ def atomic_selector
116
+ atomic_paths.selector
117
+ end
118
+
119
+ # Get all the attributes that need to be set.
120
+ #
121
+ # @example Get the sets.
122
+ # person._sets
123
+ #
124
+ # @return [ Hash ] The $set operations.
125
+ #
126
+ # @since 2.1.0
127
+ def atomic_sets
128
+ updateable? ? setters : settable? ? { atomic_path => as_document } : {}
129
+ end
130
+
131
+ private
132
+
133
+ # Get the atomic paths utility for this document.
134
+ #
135
+ # @example Get the atomic paths.
136
+ # document.atomic_paths
137
+ #
138
+ # @return [ Object ] The associated path.
139
+ #
140
+ # @since 2.1.0
141
+ def atomic_paths
142
+ @atomic_paths ||= metadata ? metadata.path(self) : Atomic::Paths::Root.new(self)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Atomic #:nodoc:
4
+
5
+ # This class contains the logic for supporting atomic operations against the
6
+ # database.
7
+ class Modifiers < Hash
8
+
9
+ # Adds push modifiers to the modifiers hash.
10
+ #
11
+ # @example Add push operations.
12
+ # modifiers.push({ "addresses" => { "street" => "Bond" }})
13
+ #
14
+ # @param [ Hash ] modifications The push modifiers.
15
+ #
16
+ # @since 2.1.0
17
+ def push(modifications)
18
+ modifications.each_pair do |field, value|
19
+ mods = conflicting?(field) ? conflicts : pushes
20
+ if mods.has_key?(field)
21
+ mods[field].push(value)
22
+ else
23
+ mods[field] = [ value ]
24
+ end
25
+ end
26
+ end
27
+
28
+ # Adds set operations to the modifiers hash.
29
+ #
30
+ # @example Add set operations.
31
+ # modifiers.set({ "title" => "sir" })
32
+ #
33
+ # @param [ Hash ] modifications The set modifiers.
34
+ #
35
+ # @since 2.1.0
36
+ def set(modifications)
37
+ modifications.each_pair do |field, value|
38
+ sets.update(field => value)
39
+ fields << field.split(".", 2)[0]
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ # Determines whether or not the provided field has a conflicting
46
+ # modification with an already added $set operation.
47
+ #
48
+ # @example Does the field conflict?
49
+ # modifiers.conflicting?("addresses")
50
+ #
51
+ # @param [ String ] field The name of the field.
52
+ #
53
+ # @return [ true, false ] If the field conflicts.
54
+ #
55
+ # @since 2.1.0
56
+ def conflicting?(field)
57
+ fields.include?(field.split(".", 2)[0])
58
+ end
59
+
60
+ # Get the push operations that would have conflicted with the sets.
61
+ #
62
+ # @example Get the conflicts.
63
+ # modifiers.conflicts
64
+ #
65
+ # @return [ Hash ] The conflicting modifications.
66
+ #
67
+ # @since 2.1.0
68
+ def conflicts
69
+ self[:other] ||= {}
70
+ end
71
+
72
+ # Get the list of stripped fields that are being updated.
73
+ #
74
+ # @example Get the fields.
75
+ # modifiers.fields
76
+ #
77
+ # @return [ Array ] The stripped field names.
78
+ #
79
+ # @since 2.1.0
80
+ def fields
81
+ @fields ||= []
82
+ end
83
+
84
+ # Get the $pushAll operations or intialize a new one.
85
+ #
86
+ # @example Get the $pushAll operations.
87
+ # modifiers.pushes
88
+ #
89
+ # @return [ Hash ] The $pushAll operations.
90
+ #
91
+ # @since 2.1.0
92
+ def pushes
93
+ self["$pushAll"] ||= {}
94
+ end
95
+
96
+ # Get the $set operations or intialize a new one.
97
+ #
98
+ # @example Get the $set operations.
99
+ # modifiers.sets
100
+ #
101
+ # @return [ Hash ] The $set operations.
102
+ #
103
+ # @since 2.1.0
104
+ def sets
105
+ self["$set"] ||= {}
106
+ end
107
+ end
108
+ end
109
+ end