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
@@ -33,6 +33,27 @@ module Mongoid # :nodoc:
33
33
  end
34
34
  end
35
35
 
36
+ class << self
37
+
38
+ # Serialize the provided object into a Mongo friendly value, using the
39
+ # field serialization method for the passed in type. If no type is
40
+ # given then we assume generic object serialization, which just returns
41
+ # the value itself.
42
+ #
43
+ # @example Mongoize the object.
44
+ # Mongoid::Serialization.mongoize(time, Time)
45
+ #
46
+ # @param [ Object ] object The object to convert.
47
+ # @param [ Class ] klass The type of the object.
48
+ #
49
+ # @return [ Object ] The converted object.
50
+ #
51
+ # @since 2.1.0
52
+ def mongoize(object, klass = Object)
53
+ Fields::Mappings.for(klass).new(:mongoize).serialize(object)
54
+ end
55
+ end
56
+
36
57
  private
37
58
 
38
59
  # For each of the provided include options, get the relation needed and
@@ -63,5 +63,39 @@ module Mongoid #:nodoc:
63
63
  def destroyed=(destroyed)
64
64
  @destroyed = destroyed && true
65
65
  end
66
+
67
+ # Determine if the document can be pushed.
68
+ #
69
+ # @example Is this pushable?
70
+ # person.pushable?
71
+ #
72
+ # @return [ true, false ] Is the document new and embedded?
73
+ def pushable?
74
+ new? && embedded_many? && _parent.persisted?
75
+ end
76
+
77
+ # Determine if the document can be set.
78
+ #
79
+ # @example Is this settable?
80
+ # person.settable?
81
+ #
82
+ # @return [ true, false ] Is this document a new embeds one?
83
+ #
84
+ # @since 2.1.0
85
+ def settable?
86
+ new? && embedded_one?
87
+ end
88
+
89
+ # Is the document updateable?
90
+ #
91
+ # @example Is the document updateable?
92
+ # person.updateable?
93
+ #
94
+ # @return [ true, false ] If the document is changed and persisted.
95
+ #
96
+ # @since 2.1.0
97
+ def updateable?
98
+ persisted? && changed?
99
+ end
66
100
  end
67
101
  end
@@ -0,0 +1,175 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # This module contains logic for easy access to objects that have a lifecycle
5
+ # on the current thread.
6
+ module Threaded
7
+ extend self
8
+
9
+ # Is the current thread in binding mode?
10
+ #
11
+ # @example Is the thread in binding mode?
12
+ # Threaded.binding?
13
+ #
14
+ # @return [ true, false ] If the thread is in binding mode?
15
+ #
16
+ # @since 2.1.0
17
+ def binding?
18
+ Thread.current[:"[mongoid]:binding-mode"] ||= false
19
+ end
20
+
21
+ # Set the binding mode for the current thread.
22
+ #
23
+ # @example Set the binding mode.
24
+ # Threaded.binding = true
25
+ #
26
+ # @param [ true, false ] mode The current binding mode.
27
+ #
28
+ # @return [ true, false ] The current binding mode.
29
+ #
30
+ # @since 2.1.0
31
+ def binding=(mode)
32
+ Thread.current[:"[mongoid]:binding-mode"] = mode
33
+ end
34
+
35
+ # Is the current thread in building mode?
36
+ #
37
+ # @example Is the thread in building mode?
38
+ # Threaded.building?
39
+ #
40
+ # @return [ true, false ] If the thread is in building mode?
41
+ #
42
+ # @since 2.1.0
43
+ def building?
44
+ Thread.current[:"[mongoid]:building-mode"] ||= false
45
+ end
46
+
47
+ # Set the building mode for the current thread.
48
+ #
49
+ # @example Set the building mode.
50
+ # Threaded.building = true
51
+ #
52
+ # @param [ true, false ] mode The current building mode.
53
+ #
54
+ # @return [ true, false ] The current building mode.
55
+ #
56
+ # @since 2.1.0
57
+ def building=(mode)
58
+ Thread.current[:"[mongoid]:building-mode"] = mode
59
+ end
60
+
61
+ # Clear out all the safety options set using the safely proxy.
62
+ #
63
+ # @example Clear out the options.
64
+ # Threaded.clear_safety_options!
65
+ #
66
+ # @return [ nil ] nil
67
+ #
68
+ # @since 2.1.0
69
+ def clear_safety_options!
70
+ Thread.current[:"[mongoid]:safety-options"] = nil
71
+ end
72
+
73
+ # Get the identity map off the current thread.
74
+ #
75
+ # @example Get the identity map.
76
+ # Threaded.identity_map
77
+ #
78
+ # @return [ IdentityMap ] The identity map.
79
+ #
80
+ # @since 2.1.0
81
+ def identity_map
82
+ Thread.current[:"[mongoid]:identity-map"] ||= IdentityMap.new
83
+ end
84
+
85
+ # Get the insert consumer from the current thread.
86
+ #
87
+ # @example Get the insert consumer.
88
+ # Threaded.insert
89
+ #
90
+ # @return [ Object ] The batch insert consumer.
91
+ #
92
+ # @since 2.1.0
93
+ def insert
94
+ Thread.current[:"[mongoid]:insert-consumer"]
95
+ end
96
+
97
+ # Set the insert consumer on the current thread.
98
+ #
99
+ # @example Set the insert consumer.
100
+ # Threaded.insert = consumer
101
+ #
102
+ # @param [ Object ] consumer The insert consumer.
103
+ #
104
+ # @return [ Object ] The insert consumer.
105
+ #
106
+ # @since 2.1.0
107
+ def insert=(consumer)
108
+ Thread.current[:"[mongoid]:insert-consumer"] = consumer
109
+ end
110
+
111
+ # Get the safety options for the current thread.
112
+ #
113
+ # @example Get the safety options.
114
+ # Threaded.safety_options
115
+ #
116
+ # @return [ Hash ] The current safety options.
117
+ #
118
+ # @since 2.1.0
119
+ def safety_options
120
+ Thread.current[:"[mongoid]:safety-options"]
121
+ end
122
+
123
+ # Set the safety options on the current thread.
124
+ #
125
+ # @example Set the safety options.
126
+ # Threaded.safety_options = { :fsync => true }
127
+ #
128
+ # @param [ Hash ] options The safety options.
129
+ #
130
+ # @return [ Hash ] The safety options.
131
+ #
132
+ # @since 2.1.0
133
+ def safety_options=(options)
134
+ Thread.current[:"[mongoid]:safety-options"] = options
135
+ end
136
+
137
+ # Get the mongoid scope stack for chained criteria.
138
+ #
139
+ # @example Get the scope stack.
140
+ # Threaded.scope_stack
141
+ #
142
+ # @return [ Hash ] The scope stack.
143
+ #
144
+ # @since 2.1.0
145
+ def scope_stack
146
+ Thread.current[:"[mongoid]:scope-stack"] ||= {}
147
+ end
148
+
149
+ # Get the update consumer from the current thread.
150
+ #
151
+ # @example Get the update consumer.
152
+ # Threaded.update
153
+ #
154
+ # @return [ Object ] The atomic update consumer.
155
+ #
156
+ # @since 2.1.0
157
+ def update
158
+ Thread.current[:"[mongoid]:update-consumer"]
159
+ end
160
+
161
+ # Set the update consumer on the current thread.
162
+ #
163
+ # @example Set the update consumer.
164
+ # Threaded.update = consumer
165
+ #
166
+ # @param [ Object ] consumer The update consumer.
167
+ #
168
+ # @return [ Object ] The update consumer.
169
+ #
170
+ # @since 2.1.0
171
+ def update=(consumer)
172
+ Thread.current[:"[mongoid]:update-consumer"] = consumer
173
+ end
174
+ end
175
+ end
@@ -26,7 +26,7 @@ module Mongoid #:nodoc:
26
26
  # @example Set the updated at time.
27
27
  # person.set_updated_at
28
28
  def set_updated_at
29
- self.updated_at = Time.now.utc
29
+ self.updated_at = Time.now.utc unless self.updated_at_changed?
30
30
  end
31
31
  end
32
32
  end
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/validations/associated"
3
- require "mongoid/validations/referenced"
4
3
  require "mongoid/validations/uniqueness"
5
4
 
6
5
  module Mongoid #:nodoc:
@@ -27,7 +26,8 @@ module Mongoid #:nodoc:
27
26
  # @since 2.0.0.rc.1
28
27
  def read_attribute_for_validation(attr)
29
28
  if relations[attr.to_s]
30
- send(attr, false, :eager => true)
29
+ relation = ivar(attr)
30
+ relation ? relation.in_memory : nil
31
31
  else
32
32
  send(attr)
33
33
  end
@@ -112,11 +112,7 @@ module Mongoid #:nodoc:
112
112
  # @since 2.0.0.rc.1
113
113
  def validates_relation(metadata)
114
114
  if metadata.validate?
115
- if metadata.embedded?
116
- validates_associated(metadata.name)
117
- else
118
- validates_with(ReferencedValidator, _merge_attributes([metadata.name]))
119
- end
115
+ validates_associated(metadata.name)
120
116
  end
121
117
  end
122
118
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
- VERSION = "2.0.2"
3
+ VERSION = "2.1.0"
4
4
  end
@@ -10,11 +10,18 @@ module Mongoid #:nodoc:
10
10
  included do
11
11
  field :version, :type => Integer, :default => 1
12
12
 
13
- embeds_many :versions, :class_name => self.name, :validate => false
13
+ embeds_many \
14
+ :versions,
15
+ :class_name => self.name,
16
+ :validate => false,
17
+ :cyclic => true,
18
+ :versioned => true
19
+
14
20
  set_callback :save, :before, :revise, :if => :revisable?
15
21
 
16
22
  class_attribute :version_max
17
23
  delegate :version_max, :to => "self.class"
24
+ self.cyclic = true
18
25
  end
19
26
 
20
27
  # Create a new version of the +Document+. This will load the previous
@@ -27,15 +34,45 @@ module Mongoid #:nodoc:
27
34
  #
28
35
  # @since 1.0.0
29
36
  def revise
30
- previous = find_last_version
31
- if previous
32
- versions.target << previous.clone
37
+ previous = previous_revision
38
+ if previous && versioned_attributes_changed?
39
+ new_version = versions.build(previous.versioned_attributes)
33
40
  versions.shift if version_max.present? && versions.length > version_max
34
41
  self.version = (version || 1 ) + 1
35
- @modifications["versions"] = [ nil, versions.as_document ] if @modifications
36
42
  end
37
43
  end
38
44
 
45
+ # Filters the results of +changes+ by removing any fields that should
46
+ # not be versioned.
47
+ #
48
+ # @return [ Hash ] A hash of versioned changed attributes.
49
+ #
50
+ # @since 2.1.0
51
+ def versioned_changes
52
+ only_versioned_attributes(changes)
53
+ end
54
+
55
+ # Filters the results of +attributes+ by removing any fields that should
56
+ # not be versioned.
57
+ #
58
+ # @return [ Hash ] A hash of versioned attributes.
59
+ #
60
+ # @since 2.1.0
61
+ def versioned_attributes
62
+ only_versioned_attributes(attributes)
63
+ end
64
+
65
+ # Check if any versioned fields have been modified. This is similar
66
+ # to +changed?+, except this method also ignores fields set to be
67
+ # ignored by versioning.
68
+ #
69
+ # @return [ Boolean ] Whether fields that will be versioned have changed.
70
+ #
71
+ # @since 2.1.0
72
+ def versioned_attributes_changed?
73
+ !versioned_changes.empty?
74
+ end
75
+
39
76
  # Executes a block that temporarily disables versioning. This is for cases
40
77
  # where you do not want to version on every save.
41
78
  #
@@ -63,7 +100,7 @@ module Mongoid #:nodoc:
63
100
  # @return [ Document, nil ] The previously saved document.
64
101
  #
65
102
  # @since 2.0.0
66
- def find_last_version
103
+ def previous_revision
67
104
  self.class.
68
105
  where(:_id => id).
69
106
  any_of({ :version => version }, { :version => nil }).first
@@ -79,7 +116,7 @@ module Mongoid #:nodoc:
79
116
  #
80
117
  # @since 2.0.0
81
118
  def revisable?
82
- changed? && !versionless?
119
+ versioned_attributes_changed? && !versionless?
83
120
  end
84
121
 
85
122
  # Are we in versionless mode? This is true if in a versionless block on the
@@ -95,6 +132,23 @@ module Mongoid #:nodoc:
95
132
  !!@versionless
96
133
  end
97
134
 
135
+ # Filters fields that should not be versioned out of an attributes hash.
136
+ # Dynamic attributes are always versioned.
137
+ #
138
+ # @param [ Hash ] A hash with field names as keys.
139
+ #
140
+ # @return [ Hash ] The hash without non-versioned columns.
141
+ #
142
+ # @since 2.1.0
143
+ def only_versioned_attributes(hash)
144
+ {}.tap do |versioned|
145
+ hash.each_pair do |name, value|
146
+ field = fields[name]
147
+ versioned[name] = value if !field || field.versioned?
148
+ end
149
+ end
150
+ end
151
+
98
152
  module ClassMethods #:nodoc:
99
153
 
100
154
  # Sets the maximum number of versions to store.
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require "rack/mongoid/middleware/identity_map"
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module Rack #:nodoc:
3
+ module Mongoid #:nodoc:
4
+ module Middleware #:nodoc:
5
+
6
+ # This middleware contains the behaviour needed to properly use the
7
+ # identity map in Rack based applications.
8
+ class IdentityMap
9
+
10
+ # Initialize the new middleware.
11
+ #
12
+ # @example Init the middleware.
13
+ # IdentityMap.new(app)
14
+ #
15
+ # @param [ Object ] app The application.
16
+ #
17
+ # @since 2.1.0
18
+ def initialize(app)
19
+ @app = app
20
+ end
21
+
22
+ # Make the request with the provided environment.
23
+ #
24
+ # @example Make the request.
25
+ # identity_map.call(env)
26
+ #
27
+ # @param [ Object ] env The environment.
28
+ #
29
+ # @return [ Array ] The status, headers, and response.
30
+ #
31
+ # @since 2.1.0
32
+ def call(env)
33
+ ::Mongoid.unit_of_work { @app.call(env) }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -15,7 +15,7 @@ module Mongoid #:nodoc:
15
15
  class_option :versioning, :type => :boolean, :default => false, :desc => "Enable mongoid versioning"
16
16
 
17
17
  def create_model_file
18
- template "model.rb", File.join("app/models", class_path, "#{file_name}.rb")
18
+ template "model.rb.tt", File.join("app/models", class_path, "#{file_name}.rb")
19
19
  end
20
20
 
21
21
  hook_for :test_framework