mongoid-multi-db 3.0.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 (276) hide show
  1. data/CHANGELOG.md +615 -0
  2. data/LICENSE +20 -0
  3. data/README.md +62 -0
  4. data/Rakefile +49 -0
  5. data/lib/config/locales/bg.yml +54 -0
  6. data/lib/config/locales/de.yml +54 -0
  7. data/lib/config/locales/en-GB.yml +55 -0
  8. data/lib/config/locales/en.yml +55 -0
  9. data/lib/config/locales/es.yml +52 -0
  10. data/lib/config/locales/fr.yml +55 -0
  11. data/lib/config/locales/hi.yml +46 -0
  12. data/lib/config/locales/hu.yml +57 -0
  13. data/lib/config/locales/id.yml +55 -0
  14. data/lib/config/locales/it.yml +52 -0
  15. data/lib/config/locales/ja.yml +50 -0
  16. data/lib/config/locales/kr.yml +47 -0
  17. data/lib/config/locales/nl.yml +52 -0
  18. data/lib/config/locales/pl.yml +52 -0
  19. data/lib/config/locales/pt-BR.yml +53 -0
  20. data/lib/config/locales/pt.yml +53 -0
  21. data/lib/config/locales/ro.yml +59 -0
  22. data/lib/config/locales/ru.yml +54 -0
  23. data/lib/config/locales/sv.yml +53 -0
  24. data/lib/config/locales/vi.yml +55 -0
  25. data/lib/config/locales/zh-CN.yml +46 -0
  26. data/lib/mongoid.rb +148 -0
  27. data/lib/mongoid/atomic.rb +230 -0
  28. data/lib/mongoid/atomic/modifiers.rb +243 -0
  29. data/lib/mongoid/atomic/paths.rb +3 -0
  30. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  31. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  32. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  33. data/lib/mongoid/atomic/paths/root.rb +40 -0
  34. data/lib/mongoid/attributes.rb +234 -0
  35. data/lib/mongoid/attributes/processing.rb +146 -0
  36. data/lib/mongoid/callbacks.rb +135 -0
  37. data/lib/mongoid/collection.rb +153 -0
  38. data/lib/mongoid/collection_proxy.rb +59 -0
  39. data/lib/mongoid/collections.rb +120 -0
  40. data/lib/mongoid/collections/master.rb +45 -0
  41. data/lib/mongoid/collections/operations.rb +44 -0
  42. data/lib/mongoid/collections/retry.rb +46 -0
  43. data/lib/mongoid/components.rb +96 -0
  44. data/lib/mongoid/config.rb +347 -0
  45. data/lib/mongoid/config/database.rb +186 -0
  46. data/lib/mongoid/config/replset_database.rb +82 -0
  47. data/lib/mongoid/connection_proxy.rb +30 -0
  48. data/lib/mongoid/contexts.rb +25 -0
  49. data/lib/mongoid/contexts/enumerable.rb +288 -0
  50. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  51. data/lib/mongoid/contexts/mongo.rb +409 -0
  52. data/lib/mongoid/copyable.rb +48 -0
  53. data/lib/mongoid/criteria.rb +418 -0
  54. data/lib/mongoid/criterion/builder.rb +34 -0
  55. data/lib/mongoid/criterion/complex.rb +84 -0
  56. data/lib/mongoid/criterion/creational.rb +34 -0
  57. data/lib/mongoid/criterion/exclusion.rb +108 -0
  58. data/lib/mongoid/criterion/inclusion.rb +305 -0
  59. data/lib/mongoid/criterion/inspection.rb +22 -0
  60. data/lib/mongoid/criterion/optional.rb +232 -0
  61. data/lib/mongoid/criterion/selector.rb +153 -0
  62. data/lib/mongoid/cursor.rb +86 -0
  63. data/lib/mongoid/database_proxy.rb +97 -0
  64. data/lib/mongoid/default_scope.rb +36 -0
  65. data/lib/mongoid/dirty.rb +110 -0
  66. data/lib/mongoid/document.rb +280 -0
  67. data/lib/mongoid/errors.rb +17 -0
  68. data/lib/mongoid/errors/callback.rb +26 -0
  69. data/lib/mongoid/errors/document_not_found.rb +28 -0
  70. data/lib/mongoid/errors/eager_load.rb +25 -0
  71. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  72. data/lib/mongoid/errors/invalid_database.rb +19 -0
  73. data/lib/mongoid/errors/invalid_field.rb +18 -0
  74. data/lib/mongoid/errors/invalid_find.rb +19 -0
  75. data/lib/mongoid/errors/invalid_options.rb +28 -0
  76. data/lib/mongoid/errors/invalid_time.rb +25 -0
  77. data/lib/mongoid/errors/invalid_type.rb +25 -0
  78. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  79. data/lib/mongoid/errors/mongoid_error.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  81. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  82. data/lib/mongoid/errors/unsupported_version.rb +20 -0
  83. data/lib/mongoid/errors/validations.rb +23 -0
  84. data/lib/mongoid/extensions.rb +82 -0
  85. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  86. data/lib/mongoid/extensions/false_class/equality.rb +26 -0
  87. data/lib/mongoid/extensions/hash/criteria_helpers.rb +45 -0
  88. data/lib/mongoid/extensions/hash/scoping.rb +25 -0
  89. data/lib/mongoid/extensions/integer/checks.rb +23 -0
  90. data/lib/mongoid/extensions/nil/collectionization.rb +23 -0
  91. data/lib/mongoid/extensions/object/checks.rb +29 -0
  92. data/lib/mongoid/extensions/object/reflections.rb +48 -0
  93. data/lib/mongoid/extensions/object/substitutable.rb +15 -0
  94. data/lib/mongoid/extensions/object/yoda.rb +44 -0
  95. data/lib/mongoid/extensions/object_id/conversions.rb +60 -0
  96. data/lib/mongoid/extensions/proc/scoping.rb +25 -0
  97. data/lib/mongoid/extensions/string/checks.rb +36 -0
  98. data/lib/mongoid/extensions/string/conversions.rb +22 -0
  99. data/lib/mongoid/extensions/string/inflections.rb +118 -0
  100. data/lib/mongoid/extensions/symbol/checks.rb +23 -0
  101. data/lib/mongoid/extensions/symbol/inflections.rb +66 -0
  102. data/lib/mongoid/extensions/true_class/equality.rb +26 -0
  103. data/lib/mongoid/extras.rb +31 -0
  104. data/lib/mongoid/factory.rb +46 -0
  105. data/lib/mongoid/fields.rb +332 -0
  106. data/lib/mongoid/fields/mappings.rb +41 -0
  107. data/lib/mongoid/fields/serializable.rb +201 -0
  108. data/lib/mongoid/fields/serializable/array.rb +49 -0
  109. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  110. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  111. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  112. data/lib/mongoid/fields/serializable/boolean.rb +43 -0
  113. data/lib/mongoid/fields/serializable/date.rb +51 -0
  114. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  115. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  116. data/lib/mongoid/fields/serializable/float.rb +32 -0
  117. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +42 -0
  118. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +47 -0
  119. data/lib/mongoid/fields/serializable/hash.rb +11 -0
  120. data/lib/mongoid/fields/serializable/integer.rb +44 -0
  121. data/lib/mongoid/fields/serializable/localized.rb +41 -0
  122. data/lib/mongoid/fields/serializable/nil_class.rb +38 -0
  123. data/lib/mongoid/fields/serializable/object.rb +11 -0
  124. data/lib/mongoid/fields/serializable/object_id.rb +31 -0
  125. data/lib/mongoid/fields/serializable/range.rb +42 -0
  126. data/lib/mongoid/fields/serializable/set.rb +42 -0
  127. data/lib/mongoid/fields/serializable/string.rb +27 -0
  128. data/lib/mongoid/fields/serializable/symbol.rb +27 -0
  129. data/lib/mongoid/fields/serializable/time.rb +23 -0
  130. data/lib/mongoid/fields/serializable/time_with_zone.rb +23 -0
  131. data/lib/mongoid/fields/serializable/timekeeping.rb +106 -0
  132. data/lib/mongoid/finders.rb +152 -0
  133. data/lib/mongoid/hierarchy.rb +120 -0
  134. data/lib/mongoid/identity.rb +92 -0
  135. data/lib/mongoid/identity_map.rb +119 -0
  136. data/lib/mongoid/indexes.rb +54 -0
  137. data/lib/mongoid/inspection.rb +54 -0
  138. data/lib/mongoid/javascript.rb +20 -0
  139. data/lib/mongoid/javascript/functions.yml +63 -0
  140. data/lib/mongoid/json.rb +16 -0
  141. data/lib/mongoid/keys.rb +144 -0
  142. data/lib/mongoid/logger.rb +39 -0
  143. data/lib/mongoid/matchers.rb +32 -0
  144. data/lib/mongoid/matchers/all.rb +21 -0
  145. data/lib/mongoid/matchers/and.rb +30 -0
  146. data/lib/mongoid/matchers/default.rb +70 -0
  147. data/lib/mongoid/matchers/exists.rb +23 -0
  148. data/lib/mongoid/matchers/gt.rb +21 -0
  149. data/lib/mongoid/matchers/gte.rb +21 -0
  150. data/lib/mongoid/matchers/in.rb +21 -0
  151. data/lib/mongoid/matchers/lt.rb +21 -0
  152. data/lib/mongoid/matchers/lte.rb +21 -0
  153. data/lib/mongoid/matchers/ne.rb +21 -0
  154. data/lib/mongoid/matchers/nin.rb +21 -0
  155. data/lib/mongoid/matchers/or.rb +33 -0
  156. data/lib/mongoid/matchers/size.rb +21 -0
  157. data/lib/mongoid/matchers/strategies.rb +93 -0
  158. data/lib/mongoid/multi_database.rb +31 -0
  159. data/lib/mongoid/multi_parameter_attributes.rb +106 -0
  160. data/lib/mongoid/named_scope.rb +146 -0
  161. data/lib/mongoid/nested_attributes.rb +54 -0
  162. data/lib/mongoid/observer.rb +170 -0
  163. data/lib/mongoid/paranoia.rb +158 -0
  164. data/lib/mongoid/persistence.rb +264 -0
  165. data/lib/mongoid/persistence/atomic.rb +223 -0
  166. data/lib/mongoid/persistence/atomic/add_to_set.rb +35 -0
  167. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  168. data/lib/mongoid/persistence/atomic/inc.rb +31 -0
  169. data/lib/mongoid/persistence/atomic/operation.rb +85 -0
  170. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  171. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  172. data/lib/mongoid/persistence/atomic/pull_all.rb +34 -0
  173. data/lib/mongoid/persistence/atomic/push.rb +31 -0
  174. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  175. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  176. data/lib/mongoid/persistence/atomic/sets.rb +30 -0
  177. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  178. data/lib/mongoid/persistence/deletion.rb +32 -0
  179. data/lib/mongoid/persistence/insertion.rb +41 -0
  180. data/lib/mongoid/persistence/modification.rb +37 -0
  181. data/lib/mongoid/persistence/operations.rb +211 -0
  182. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  183. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  184. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  185. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  186. data/lib/mongoid/persistence/operations/update.rb +64 -0
  187. data/lib/mongoid/railtie.rb +126 -0
  188. data/lib/mongoid/railties/database.rake +182 -0
  189. data/lib/mongoid/railties/document.rb +12 -0
  190. data/lib/mongoid/relations.rb +144 -0
  191. data/lib/mongoid/relations/accessors.rb +138 -0
  192. data/lib/mongoid/relations/auto_save.rb +38 -0
  193. data/lib/mongoid/relations/binding.rb +26 -0
  194. data/lib/mongoid/relations/bindings.rb +9 -0
  195. data/lib/mongoid/relations/bindings/embedded/in.rb +69 -0
  196. data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
  197. data/lib/mongoid/relations/bindings/embedded/one.rb +61 -0
  198. data/lib/mongoid/relations/bindings/referenced/in.rb +76 -0
  199. data/lib/mongoid/relations/bindings/referenced/many.rb +54 -0
  200. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +51 -0
  201. data/lib/mongoid/relations/bindings/referenced/one.rb +58 -0
  202. data/lib/mongoid/relations/builder.rb +57 -0
  203. data/lib/mongoid/relations/builders.rb +83 -0
  204. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  205. data/lib/mongoid/relations/builders/embedded/many.rb +40 -0
  206. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  207. data/lib/mongoid/relations/builders/nested_attributes/many.rb +110 -0
  208. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  209. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  210. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  211. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +38 -0
  212. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  213. data/lib/mongoid/relations/cascading.rb +56 -0
  214. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  215. data/lib/mongoid/relations/cascading/destroy.rb +26 -0
  216. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  217. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  218. data/lib/mongoid/relations/constraint.rb +42 -0
  219. data/lib/mongoid/relations/conversions.rb +35 -0
  220. data/lib/mongoid/relations/cyclic.rb +103 -0
  221. data/lib/mongoid/relations/embedded/atomic.rb +89 -0
  222. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  223. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  224. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  225. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  226. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  227. data/lib/mongoid/relations/embedded/in.rb +220 -0
  228. data/lib/mongoid/relations/embedded/many.rb +560 -0
  229. data/lib/mongoid/relations/embedded/one.rb +206 -0
  230. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  231. data/lib/mongoid/relations/macros.rb +310 -0
  232. data/lib/mongoid/relations/many.rb +135 -0
  233. data/lib/mongoid/relations/metadata.rb +919 -0
  234. data/lib/mongoid/relations/nested_builder.rb +75 -0
  235. data/lib/mongoid/relations/one.rb +36 -0
  236. data/lib/mongoid/relations/options.rb +47 -0
  237. data/lib/mongoid/relations/polymorphic.rb +40 -0
  238. data/lib/mongoid/relations/proxy.rb +145 -0
  239. data/lib/mongoid/relations/referenced/batch.rb +72 -0
  240. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  241. data/lib/mongoid/relations/referenced/in.rb +262 -0
  242. data/lib/mongoid/relations/referenced/many.rb +623 -0
  243. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  244. data/lib/mongoid/relations/referenced/one.rb +272 -0
  245. data/lib/mongoid/relations/reflections.rb +62 -0
  246. data/lib/mongoid/relations/synchronization.rb +153 -0
  247. data/lib/mongoid/relations/targets.rb +2 -0
  248. data/lib/mongoid/relations/targets/enumerable.rb +372 -0
  249. data/lib/mongoid/reloading.rb +91 -0
  250. data/lib/mongoid/safety.rb +105 -0
  251. data/lib/mongoid/scope.rb +31 -0
  252. data/lib/mongoid/serialization.rb +134 -0
  253. data/lib/mongoid/sharding.rb +61 -0
  254. data/lib/mongoid/state.rb +97 -0
  255. data/lib/mongoid/threaded.rb +530 -0
  256. data/lib/mongoid/threaded/lifecycle.rb +192 -0
  257. data/lib/mongoid/timestamps.rb +15 -0
  258. data/lib/mongoid/timestamps/created.rb +24 -0
  259. data/lib/mongoid/timestamps/timeless.rb +50 -0
  260. data/lib/mongoid/timestamps/updated.rb +26 -0
  261. data/lib/mongoid/validations.rb +140 -0
  262. data/lib/mongoid/validations/associated.rb +46 -0
  263. data/lib/mongoid/validations/uniqueness.rb +145 -0
  264. data/lib/mongoid/version.rb +4 -0
  265. data/lib/mongoid/versioning.rb +185 -0
  266. data/lib/rack/mongoid.rb +2 -0
  267. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  268. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  269. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  270. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  271. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  272. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  273. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  274. data/lib/rails/generators/mongoid_generator.rb +70 -0
  275. data/lib/rails/mongoid.rb +91 -0
  276. metadata +465 -0
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Validations #:nodoc:
4
+
5
+ # Validates whether or not an association is valid or not. Will correctly
6
+ # handle has one and has many associations.
7
+ #
8
+ # @example Set up the association validations.
9
+ #
10
+ # class Person
11
+ # include Mongoid::Document
12
+ # embeds_one :name
13
+ # embeds_many :addresses
14
+ #
15
+ # validates_associated :name, :addresses
16
+ # end
17
+ class AssociatedValidator < ActiveModel::EachValidator
18
+
19
+ # Validates that the associations provided are either all nil or all
20
+ # valid. If neither is true then the appropriate errors will be added to
21
+ # the parent document.
22
+ #
23
+ # @example Validate the association.
24
+ # validator.validate_each(document, :name, name)
25
+ #
26
+ # @param [ Document ] document The document to validate.
27
+ # @param [ Symbol ] attribute The relation to validate.
28
+ # @param [ Object ] value The value of the relation.
29
+ def validate_each(document, attribute, value)
30
+ begin
31
+ document.begin_validate
32
+ valid = Array.wrap(value).collect do |doc|
33
+ if doc.nil?
34
+ true
35
+ else
36
+ doc.validated? ? true : doc.valid?
37
+ end
38
+ end.all?
39
+ ensure
40
+ document.exit_validate
41
+ end
42
+ document.errors.add(attribute, :invalid) unless valid
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,145 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Validations #:nodoc:
4
+
5
+ # Validates whether or not a field is unique against the documents in the
6
+ # database.
7
+ #
8
+ # @example Define the uniqueness validator.
9
+ #
10
+ # class Person
11
+ # include Mongoid::Document
12
+ # field :title
13
+ #
14
+ # validates_uniqueness_of :title
15
+ # end
16
+ class UniquenessValidator < ActiveModel::EachValidator
17
+ attr_reader :klass
18
+
19
+ # Unfortunately, we have to tie Uniqueness validators to a class.
20
+ #
21
+ # @example Setup the validator.
22
+ # UniquenessValidator.new.setup(Person)
23
+ #
24
+ # @param [ Class ] klass The class getting validated.
25
+ #
26
+ # @since 1.0.0
27
+ def setup(klass)
28
+ @klass = klass
29
+ end
30
+
31
+ # Validate the document for uniqueness violations.
32
+ #
33
+ # @example Validate the document.
34
+ # validate_each(person, :title, "Sir")
35
+ #
36
+ # @param [ Document ] document The document to validate.
37
+ # @param [ Symbol ] attribute The field to validate on.
38
+ # @param [ Object ] value The value of the field.
39
+ #
40
+ # @return [ Errors ] The errors.
41
+ #
42
+ # @since 1.0.0
43
+ def validate_each(document, attribute, value)
44
+ if document.embedded?
45
+ return if skip_validation?(document)
46
+ relation = document._parent.send(document.metadata.name)
47
+ criteria = relation.where(criterion(document, attribute, value))
48
+ criteria = scope(criteria, document, attribute)
49
+ if document.primary_key == Array.wrap(attribute)
50
+ document.errors.add(attribute, :taken) if criteria.count > 1
51
+ else
52
+ document.errors.add(attribute, :taken) if criteria.exists?
53
+ end
54
+ else
55
+ criteria = klass.where(criterion(document, attribute, value))
56
+ criteria = scope(criteria, document, attribute)
57
+ document.errors.add(attribute, :taken) if criteria.exists?
58
+ end
59
+ end
60
+
61
+ protected
62
+
63
+ # Should the uniqueness validation be case sensitive?
64
+ #
65
+ # @example Is the validation case sensitive?
66
+ # validator.case_sensitive?
67
+ #
68
+ # @return [ true, false ] If the validation is case sensitive.
69
+ #
70
+ # @since 2.3.0
71
+ def case_sensitive?
72
+ !(options[:case_sensitive] == false)
73
+ end
74
+
75
+ # Get the default criteria for checking uniqueness.
76
+ #
77
+ # @example Get the criteria.
78
+ # validator.criterion(person, :title, "Sir")
79
+ #
80
+ # @param [ Document ] document The document to validate.
81
+ # @param [ Symbol ] attribute The name of the attribute.
82
+ # @param [ Object ] value The value of the object.
83
+ #
84
+ # @return [ Criteria ] The uniqueness criteria.
85
+ #
86
+ # @since 2.3.0
87
+ def criterion(document, attribute, value)
88
+ { attribute => filter(value) }.tap do |selector|
89
+ if document.persisted? ||
90
+ (document.embedded? && (document.primary_key != Array.wrap(attribute)))
91
+ selector.merge!(:_id => { "$ne" => document.id })
92
+ end
93
+ end
94
+ end
95
+
96
+ # Filter the value based on whether the check is case sensitive or not.
97
+ #
98
+ # @example Filter the value.
99
+ # validator.filter("testing")
100
+ #
101
+ # @param [ Object ] value The value to filter.
102
+ #
103
+ # @return [ Object, Regexp ] The value, filtered or not.
104
+ #
105
+ # @since 2.3.0
106
+ def filter(value)
107
+ !case_sensitive? && value ? /^#{Regexp.escape(value.to_s)}$/i : value
108
+ end
109
+
110
+ # Scope the criteria to the scope options provided.
111
+ #
112
+ # @example Scope the criteria.
113
+ # validator.scope(criteria, document)
114
+ #
115
+ # @param [ Criteria ] criteria The criteria to scope.
116
+ # @param [ Document ] document The document being validated.
117
+ #
118
+ # @return [ Criteria ] The scoped criteria.
119
+ #
120
+ # @since 2.3.0
121
+ def scope(criteria, document, attribute)
122
+ unless document.primary_key == Array.wrap(attribute)
123
+ Array.wrap(options[:scope]).each do |item|
124
+ criteria = criteria.where(item => document.attributes[item.to_s])
125
+ end
126
+ end
127
+ criteria
128
+ end
129
+
130
+ # Should validation be skipped?
131
+ #
132
+ # @example Should the validation be skipped?
133
+ # validator.skip_validation?(doc)
134
+ #
135
+ # @param [ Document ] document The embedded document.
136
+ #
137
+ # @return [ true, false ] If the validation should be skipped.
138
+ #
139
+ # @since 2.3.0
140
+ def skip_validation?(document)
141
+ !document._parent || document.embedded_one?
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ VERSION = "3.0.0"
4
+ end
@@ -0,0 +1,185 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # Include this module to get automatic versioning of root level documents.
5
+ # This will add a version field to the +Document+ and a has_many association
6
+ # with all the versions contained in it.
7
+ module Versioning
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ field :version, :type => Integer, :default => 1
12
+
13
+ embeds_many \
14
+ :versions,
15
+ :class_name => self.name,
16
+ :validate => false,
17
+ :cyclic => true,
18
+ :inverse_of => nil,
19
+ :versioned => true
20
+
21
+ set_callback :save, :before, :revise, :if => :revisable?
22
+
23
+ class_attribute :version_max
24
+ self.cyclic = true
25
+ end
26
+
27
+ # Create a new version of the +Document+. This will load the previous
28
+ # document from the database and set it as the next version before saving
29
+ # the current document. It then increments the version number. If a #max_versions
30
+ # limit is set in the model and it's exceeded, the oldest version gets discarded.
31
+ #
32
+ # @example Revise the document.
33
+ # person.revise
34
+ #
35
+ # @since 1.0.0
36
+ def revise
37
+ previous = previous_revision
38
+ if previous && versioned_attributes_changed?
39
+ versions.build(previous.versioned_attributes).attributes.delete("_id")
40
+ if version_max.present? && versions.length > version_max
41
+ versions.delete(versions.first)
42
+ end
43
+ self.version = (version || 1 ) + 1
44
+ end
45
+ end
46
+
47
+ # Forces the creation of a new version of the +Document+, regardless of
48
+ # whether a change was actually made.
49
+ #
50
+ # @example Revise the document.
51
+ # person.revise!
52
+ #
53
+ # @since 2.2.1
54
+ def revise!
55
+ new_version = versions.build((previous_revision || self).versioned_attributes)
56
+ versions.shift if version_max.present? && versions.length > version_max
57
+ self.version = (version || 1 ) + 1
58
+ save
59
+ end
60
+
61
+ # Filters the results of +changes+ by removing any fields that should
62
+ # not be versioned.
63
+ #
64
+ # @return [ Hash ] A hash of versioned changed attributes.
65
+ #
66
+ # @since 2.1.0
67
+ def versioned_changes
68
+ only_versioned_attributes(changes)
69
+ end
70
+
71
+ # Filters the results of +attributes+ by removing any fields that should
72
+ # not be versioned.
73
+ #
74
+ # @return [ Hash ] A hash of versioned attributes.
75
+ #
76
+ # @since 2.1.0
77
+ def versioned_attributes
78
+ only_versioned_attributes(attributes)
79
+ end
80
+
81
+ # Check if any versioned fields have been modified. This is similar
82
+ # to +changed?+, except this method also ignores fields set to be
83
+ # ignored by versioning.
84
+ #
85
+ # @return [ Boolean ] Whether fields that will be versioned have changed.
86
+ #
87
+ # @since 2.1.0
88
+ def versioned_attributes_changed?
89
+ !versioned_changes.empty?
90
+ end
91
+
92
+ # Executes a block that temporarily disables versioning. This is for cases
93
+ # where you do not want to version on every save.
94
+ #
95
+ # @example Execute a save without versioning.
96
+ # person.versionless(&:save)
97
+ #
98
+ # @return [ Object ] The document or result of the block execution.
99
+ #
100
+ # @since 2.0.0
101
+ def versionless
102
+ @versionless = true
103
+ result = yield(self) if block_given?
104
+ @versionless = false
105
+ result || self
106
+ end
107
+
108
+ private
109
+
110
+ # Find the previous version of this document in the database, or if the
111
+ # document had been saved without versioning return the persisted one.
112
+ #
113
+ # @example Find the last version.
114
+ # document.find_last_version
115
+ #
116
+ # @return [ Document, nil ] The previously saved document.
117
+ #
118
+ # @since 2.0.0
119
+ def previous_revision
120
+ _loading_revision do
121
+ self.class.
122
+ where(:_id => id).
123
+ any_of({ :version => version }, { :version => nil }).first
124
+ end
125
+ end
126
+
127
+ # Is the document able to be revised? This is true if the document has
128
+ # changed and we have not explicitly told it not to version.
129
+ #
130
+ # @example Is the document revisable?
131
+ # document.revisable?
132
+ #
133
+ # @return [ true, false ] If the document is revisable.
134
+ #
135
+ # @since 2.0.0
136
+ def revisable?
137
+ versioned_attributes_changed? && !versionless?
138
+ end
139
+
140
+ # Are we in versionless mode? This is true if in a versionless block on the
141
+ # document.
142
+ #
143
+ # @example Is the document in versionless mode?
144
+ # document.versionless?
145
+ #
146
+ # @return [ true, false ] Is the document not currently versioning.
147
+ #
148
+ # @since 2.0.0
149
+ def versionless?
150
+ !!@versionless
151
+ end
152
+
153
+ # Filters fields that should not be versioned out of an attributes hash.
154
+ # Dynamic attributes are always versioned.
155
+ #
156
+ # @param [ Hash ] A hash with field names as keys.
157
+ #
158
+ # @return [ Hash ] The hash without non-versioned columns.
159
+ #
160
+ # @since 2.1.0
161
+ def only_versioned_attributes(hash)
162
+ {}.tap do |versioned|
163
+ hash.except("versions").each_pair do |name, value|
164
+ field = fields[name]
165
+ versioned[name] = value if !field || field.versioned?
166
+ end
167
+ end
168
+ end
169
+
170
+ module ClassMethods #:nodoc:
171
+
172
+ # Sets the maximum number of versions to store.
173
+ #
174
+ # @example Set the maximum.
175
+ # Person.max_versions(5)
176
+ #
177
+ # @param [ Integer ] number The maximum number to store.
178
+ #
179
+ # @return [ Integer ] The max number of versions.
180
+ def max_versions(number)
181
+ self.version_max = number.to_i
182
+ end
183
+ end
184
+ end
185
+ end
@@ -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
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ require 'rails/generators/mongoid_generator'
3
+
4
+ module Mongoid
5
+ module Generators
6
+ class ConfigGenerator < Rails::Generators::Base
7
+ desc "Creates a Mongoid configuration file at config/mongoid.yml"
8
+
9
+ argument :database_name, :type => :string, :optional => true
10
+
11
+ def self.source_root
12
+ @_mongoid_source_root ||= File.expand_path("../templates", __FILE__)
13
+ end
14
+
15
+ def app_name
16
+ Rails::Application.subclasses.first.parent.to_s.underscore
17
+ end
18
+
19
+ def create_config_file
20
+ template 'mongoid.yml', File.join('config', "mongoid.yml")
21
+ end
22
+
23
+ end
24
+ end
25
+ end