mongoid 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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