mongoid-braxton 2.0.2

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 (226) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +50 -0
  3. data/Rakefile +51 -0
  4. data/lib/config/locales/bg.yml +41 -0
  5. data/lib/config/locales/de.yml +41 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +41 -0
  8. data/lib/config/locales/fr.yml +42 -0
  9. data/lib/config/locales/hu.yml +44 -0
  10. data/lib/config/locales/id.yml +46 -0
  11. data/lib/config/locales/it.yml +39 -0
  12. data/lib/config/locales/ja.yml +40 -0
  13. data/lib/config/locales/kr.yml +65 -0
  14. data/lib/config/locales/nl.yml +39 -0
  15. data/lib/config/locales/pl.yml +39 -0
  16. data/lib/config/locales/pt-BR.yml +40 -0
  17. data/lib/config/locales/pt.yml +40 -0
  18. data/lib/config/locales/ro.yml +46 -0
  19. data/lib/config/locales/ru.yml +41 -0
  20. data/lib/config/locales/sv.yml +40 -0
  21. data/lib/config/locales/vi.yml +45 -0
  22. data/lib/config/locales/zh-CN.yml +33 -0
  23. data/lib/mongoid.rb +140 -0
  24. data/lib/mongoid/atomicity.rb +111 -0
  25. data/lib/mongoid/attributes.rb +185 -0
  26. data/lib/mongoid/attributes/processing.rb +145 -0
  27. data/lib/mongoid/callbacks.rb +23 -0
  28. data/lib/mongoid/collection.rb +137 -0
  29. data/lib/mongoid/collections.rb +71 -0
  30. data/lib/mongoid/collections/master.rb +37 -0
  31. data/lib/mongoid/collections/operations.rb +42 -0
  32. data/lib/mongoid/collections/retry.rb +39 -0
  33. data/lib/mongoid/components.rb +45 -0
  34. data/lib/mongoid/config.rb +349 -0
  35. data/lib/mongoid/config/database.rb +167 -0
  36. data/lib/mongoid/config/replset_database.rb +78 -0
  37. data/lib/mongoid/contexts.rb +19 -0
  38. data/lib/mongoid/contexts/enumerable.rb +275 -0
  39. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  40. data/lib/mongoid/contexts/mongo.rb +345 -0
  41. data/lib/mongoid/copyable.rb +46 -0
  42. data/lib/mongoid/criteria.rb +357 -0
  43. data/lib/mongoid/criterion/builder.rb +34 -0
  44. data/lib/mongoid/criterion/complex.rb +34 -0
  45. data/lib/mongoid/criterion/creational.rb +34 -0
  46. data/lib/mongoid/criterion/exclusion.rb +108 -0
  47. data/lib/mongoid/criterion/inclusion.rb +198 -0
  48. data/lib/mongoid/criterion/inspection.rb +22 -0
  49. data/lib/mongoid/criterion/optional.rb +193 -0
  50. data/lib/mongoid/criterion/selector.rb +143 -0
  51. data/lib/mongoid/criterion/unconvertable.rb +20 -0
  52. data/lib/mongoid/cursor.rb +86 -0
  53. data/lib/mongoid/default_scope.rb +36 -0
  54. data/lib/mongoid/dirty.rb +253 -0
  55. data/lib/mongoid/document.rb +284 -0
  56. data/lib/mongoid/errors.rb +13 -0
  57. data/lib/mongoid/errors/document_not_found.rb +29 -0
  58. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  59. data/lib/mongoid/errors/invalid_database.rb +20 -0
  60. data/lib/mongoid/errors/invalid_field.rb +19 -0
  61. data/lib/mongoid/errors/invalid_options.rb +16 -0
  62. data/lib/mongoid/errors/invalid_type.rb +26 -0
  63. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  64. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  65. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  66. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  67. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  68. data/lib/mongoid/errors/validations.rb +24 -0
  69. data/lib/mongoid/extensions.rb +123 -0
  70. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  71. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  72. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  74. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  75. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  76. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  77. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  78. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  79. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  80. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  81. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  84. data/lib/mongoid/extensions/object/checks.rb +32 -0
  85. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  86. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  87. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  88. data/lib/mongoid/extensions/object_id/conversions.rb +96 -0
  89. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  90. data/lib/mongoid/extensions/range/conversions.rb +25 -0
  91. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  92. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  93. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  94. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  95. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  96. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  97. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  98. data/lib/mongoid/extras.rb +42 -0
  99. data/lib/mongoid/factory.rb +37 -0
  100. data/lib/mongoid/field.rb +162 -0
  101. data/lib/mongoid/fields.rb +183 -0
  102. data/lib/mongoid/finders.rb +127 -0
  103. data/lib/mongoid/hierarchy.rb +85 -0
  104. data/lib/mongoid/identity.rb +92 -0
  105. data/lib/mongoid/indexes.rb +38 -0
  106. data/lib/mongoid/inspection.rb +54 -0
  107. data/lib/mongoid/javascript.rb +21 -0
  108. data/lib/mongoid/javascript/functions.yml +37 -0
  109. data/lib/mongoid/json.rb +16 -0
  110. data/lib/mongoid/keys.rb +131 -0
  111. data/lib/mongoid/logger.rb +18 -0
  112. data/lib/mongoid/matchers.rb +32 -0
  113. data/lib/mongoid/matchers/all.rb +11 -0
  114. data/lib/mongoid/matchers/default.rb +70 -0
  115. data/lib/mongoid/matchers/exists.rb +13 -0
  116. data/lib/mongoid/matchers/gt.rb +11 -0
  117. data/lib/mongoid/matchers/gte.rb +11 -0
  118. data/lib/mongoid/matchers/in.rb +11 -0
  119. data/lib/mongoid/matchers/lt.rb +11 -0
  120. data/lib/mongoid/matchers/lte.rb +11 -0
  121. data/lib/mongoid/matchers/ne.rb +11 -0
  122. data/lib/mongoid/matchers/nin.rb +11 -0
  123. data/lib/mongoid/matchers/or.rb +30 -0
  124. data/lib/mongoid/matchers/size.rb +11 -0
  125. data/lib/mongoid/matchers/strategies.rb +63 -0
  126. data/lib/mongoid/multi_database.rb +11 -0
  127. data/lib/mongoid/multi_parameter_attributes.rb +82 -0
  128. data/lib/mongoid/named_scope.rb +137 -0
  129. data/lib/mongoid/nested_attributes.rb +51 -0
  130. data/lib/mongoid/observer.rb +67 -0
  131. data/lib/mongoid/paranoia.rb +103 -0
  132. data/lib/mongoid/paths.rb +61 -0
  133. data/lib/mongoid/persistence.rb +240 -0
  134. data/lib/mongoid/persistence/atomic.rb +88 -0
  135. data/lib/mongoid/persistence/atomic/add_to_set.rb +32 -0
  136. data/lib/mongoid/persistence/atomic/inc.rb +28 -0
  137. data/lib/mongoid/persistence/atomic/operation.rb +44 -0
  138. data/lib/mongoid/persistence/atomic/pull_all.rb +33 -0
  139. data/lib/mongoid/persistence/atomic/push.rb +28 -0
  140. data/lib/mongoid/persistence/command.rb +71 -0
  141. data/lib/mongoid/persistence/insert.rb +53 -0
  142. data/lib/mongoid/persistence/insert_embedded.rb +43 -0
  143. data/lib/mongoid/persistence/remove.rb +44 -0
  144. data/lib/mongoid/persistence/remove_all.rb +40 -0
  145. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  146. data/lib/mongoid/persistence/update.rb +77 -0
  147. data/lib/mongoid/railtie.rb +139 -0
  148. data/lib/mongoid/railties/database.rake +171 -0
  149. data/lib/mongoid/railties/document.rb +12 -0
  150. data/lib/mongoid/relations.rb +107 -0
  151. data/lib/mongoid/relations/accessors.rb +175 -0
  152. data/lib/mongoid/relations/auto_save.rb +34 -0
  153. data/lib/mongoid/relations/binding.rb +26 -0
  154. data/lib/mongoid/relations/bindings.rb +9 -0
  155. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  156. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  157. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  158. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  159. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  160. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +103 -0
  161. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  162. data/lib/mongoid/relations/builder.rb +42 -0
  163. data/lib/mongoid/relations/builders.rb +79 -0
  164. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  165. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  166. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  167. data/lib/mongoid/relations/builders/nested_attributes/many.rb +126 -0
  168. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  169. data/lib/mongoid/relations/builders/referenced/in.rb +29 -0
  170. data/lib/mongoid/relations/builders/referenced/many.rb +47 -0
  171. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  172. data/lib/mongoid/relations/builders/referenced/one.rb +27 -0
  173. data/lib/mongoid/relations/cascading.rb +55 -0
  174. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  175. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  176. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  177. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  178. data/lib/mongoid/relations/constraint.rb +42 -0
  179. data/lib/mongoid/relations/cyclic.rb +103 -0
  180. data/lib/mongoid/relations/embedded/atomic.rb +86 -0
  181. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  182. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  183. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  184. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  185. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  186. data/lib/mongoid/relations/embedded/in.rb +173 -0
  187. data/lib/mongoid/relations/embedded/many.rb +499 -0
  188. data/lib/mongoid/relations/embedded/one.rb +170 -0
  189. data/lib/mongoid/relations/macros.rb +310 -0
  190. data/lib/mongoid/relations/many.rb +215 -0
  191. data/lib/mongoid/relations/metadata.rb +539 -0
  192. data/lib/mongoid/relations/nested_builder.rb +68 -0
  193. data/lib/mongoid/relations/one.rb +47 -0
  194. data/lib/mongoid/relations/polymorphic.rb +54 -0
  195. data/lib/mongoid/relations/proxy.rb +143 -0
  196. data/lib/mongoid/relations/referenced/batch.rb +71 -0
  197. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  198. data/lib/mongoid/relations/referenced/in.rb +216 -0
  199. data/lib/mongoid/relations/referenced/many.rb +516 -0
  200. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  201. data/lib/mongoid/relations/referenced/one.rb +222 -0
  202. data/lib/mongoid/relations/reflections.rb +45 -0
  203. data/lib/mongoid/safe.rb +23 -0
  204. data/lib/mongoid/safety.rb +207 -0
  205. data/lib/mongoid/scope.rb +31 -0
  206. data/lib/mongoid/serialization.rb +99 -0
  207. data/lib/mongoid/sharding.rb +51 -0
  208. data/lib/mongoid/state.rb +67 -0
  209. data/lib/mongoid/timestamps.rb +14 -0
  210. data/lib/mongoid/timestamps/created.rb +31 -0
  211. data/lib/mongoid/timestamps/updated.rb +33 -0
  212. data/lib/mongoid/validations.rb +124 -0
  213. data/lib/mongoid/validations/associated.rb +44 -0
  214. data/lib/mongoid/validations/referenced.rb +58 -0
  215. data/lib/mongoid/validations/uniqueness.rb +85 -0
  216. data/lib/mongoid/version.rb +4 -0
  217. data/lib/mongoid/versioning.rb +113 -0
  218. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  219. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  220. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  221. data/lib/rails/generators/mongoid/model/templates/model.rb +19 -0
  222. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  223. data/lib/rails/generators/mongoid/observer/templates/observer.rb +4 -0
  224. data/lib/rails/generators/mongoid_generator.rb +70 -0
  225. data/lib/rails/mongoid.rb +58 -0
  226. metadata +406 -0
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # This module contains the behaviour for getting the various states a
5
+ # document can transition through.
6
+ module State
7
+
8
+ # Returns true if the +Document+ has not been persisted to the database,
9
+ # false if it has. This is determined by the variable @new_record
10
+ # and NOT if the object has an id.
11
+ #
12
+ # @example Is the document new?
13
+ # person.new_record?
14
+ #
15
+ # @return [ true, false ] True if new, false if not.
16
+ def new_record?
17
+ @new_record == true
18
+ end
19
+ alias :new? :new_record?
20
+
21
+ # Sets the new_record boolean - used after document is saved.
22
+ #
23
+ # @example Set whether the document is new.
24
+ # person.new_record = true
25
+ #
26
+ # @param [ true, false ] saved The value to set for new_record.
27
+ #
28
+ # @return [ true, false ] The new_record value.
29
+ def new_record=(saved)
30
+ @new_record = saved
31
+ end
32
+
33
+ # Checks if the document has been saved to the database. Returns false
34
+ # if the document has been destroyed.
35
+ #
36
+ # @example Is the document persisted?
37
+ # person.persisted?
38
+ #
39
+ # @return [ true, false ] True if persisted, false if not.
40
+ def persisted?
41
+ !new_record? && !destroyed?
42
+ end
43
+
44
+ # Returns true if the +Document+ has been succesfully destroyed, and false
45
+ # if it hasn't. This is determined by the variable @destroyed and NOT
46
+ # by checking the database.
47
+ #
48
+ # @example Is the document destroyed?
49
+ # person.destroyed?
50
+ #
51
+ # @return [ true, false ] True if destroyed, false if not.
52
+ def destroyed?
53
+ @destroyed == true
54
+ end
55
+ alias :deleted? :destroyed?
56
+
57
+ # Sets the destroyed boolean - used after document is destroyed.
58
+ #
59
+ # @example Set the destroyed flag.
60
+ # person.destroyed = true
61
+ #
62
+ # @return [ true, false ] The value set for destroyed.
63
+ def destroyed=(destroyed)
64
+ @destroyed = destroyed && true
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ require "mongoid/timestamps/created"
3
+ require "mongoid/timestamps/updated"
4
+
5
+ module Mongoid #:nodoc:
6
+
7
+ # This module handles the behaviour for setting up document created at and
8
+ # updated at timestamps.
9
+ module Timestamps
10
+ extend ActiveSupport::Concern
11
+ include Created
12
+ include Updated
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ module Timestamps
5
+ # This module handles the behaviour for setting up document created at
6
+ # timestamp.
7
+ module Created
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ field :created_at, :type => Time
12
+
13
+ set_callback :create, :before, :set_created_at
14
+
15
+ unless methods.include? 'record_timestamps'
16
+ class_attribute :record_timestamps
17
+ self.record_timestamps = true
18
+ end
19
+ end
20
+
21
+ # Update the created_at field on the Document to the current time. This is
22
+ # only called on create.
23
+ #
24
+ # @example Set the created at time.
25
+ # person.set_created_at
26
+ def set_created_at
27
+ self.created_at = Time.now.utc if !created_at
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ module Timestamps
5
+ # This module handles the behaviour for setting up document updated at
6
+ # timestamp.
7
+ module Updated
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ field :updated_at, :type => Time
12
+
13
+ set_callback :save, :before, :set_updated_at, :if => Proc.new { |doc|
14
+ doc.new_record? || doc.changed?
15
+ }
16
+
17
+ unless methods.include? 'record_timestamps'
18
+ class_attribute :record_timestamps
19
+ self.record_timestamps = true
20
+ end
21
+ end
22
+
23
+ # Update the updated_at field on the Document to the current time.
24
+ # This is only called on create and on save.
25
+ #
26
+ # @example Set the updated at time.
27
+ # person.set_updated_at
28
+ def set_updated_at
29
+ self.updated_at = Time.now.utc
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,124 @@
1
+ # encoding: utf-8
2
+ require "mongoid/validations/associated"
3
+ require "mongoid/validations/referenced"
4
+ require "mongoid/validations/uniqueness"
5
+
6
+ module Mongoid #:nodoc:
7
+
8
+ # This module provides additional validations that ActiveModel does not
9
+ # provide: validates_associated and validates_uniqueness_of.
10
+ module Validations
11
+ extend ActiveSupport::Concern
12
+ include ActiveModel::Validations
13
+
14
+ attr_accessor :validated
15
+
16
+ # Overrides the default ActiveModel behaviour since we need to handle
17
+ # validations of relations slightly different than just calling the
18
+ # getter.
19
+ #
20
+ # @example Read the value.
21
+ # person.read_attribute_for_validation(:addresses)
22
+ #
23
+ # @param [ Symbol ] attr The name of the field or relation.
24
+ #
25
+ # @return [ Object ] The value of the field or the relation.
26
+ #
27
+ # @since 2.0.0.rc.1
28
+ def read_attribute_for_validation(attr)
29
+ if relations[attr.to_s]
30
+ send(attr, false, :eager => true)
31
+ else
32
+ send(attr)
33
+ end
34
+ end
35
+
36
+ # Determine if the document is valid.
37
+ #
38
+ # @example Is the document valid?
39
+ # person.valid?
40
+ #
41
+ # @example Is the document valid in a context?
42
+ # person.valid?(:create)
43
+ #
44
+ # @param [ Symbol ] context The optional validation context.
45
+ #
46
+ # @return [ true, false ] True if valid, false if not.
47
+ #
48
+ # @since 2.0.0.rc.6
49
+ def valid?(context = nil)
50
+ super context ? context : (new? ? :create : :update)
51
+ end
52
+
53
+ # Used to prevent infinite loops in associated validations.
54
+ #
55
+ # @example Is the document validated?
56
+ # document.validated?
57
+ #
58
+ # @return [ true, false ] Has the document already been validated?
59
+ #
60
+ # @since 2.0.0.rc.2
61
+ def validated?
62
+ !!@validated
63
+ end
64
+
65
+ module ClassMethods #:nodoc:
66
+
67
+ # Validates whether or not an association is valid or not. Will correctly
68
+ # handle has one and has many associations.
69
+ #
70
+ # @example
71
+ #
72
+ # class Person
73
+ # include Mongoid::Document
74
+ # embeds_one :name
75
+ # embeds_many :addresses
76
+ #
77
+ # validates_associated :name, :addresses
78
+ # end
79
+ #
80
+ # @param [ Array ] *args The arguments to pass to the validator.
81
+ def validates_associated(*args)
82
+ validates_with(AssociatedValidator, _merge_attributes(args))
83
+ end
84
+
85
+ # Validates whether or not a field is unique against the documents in the
86
+ # database.
87
+ #
88
+ # @example
89
+ #
90
+ # class Person
91
+ # include Mongoid::Document
92
+ # field :title
93
+ #
94
+ # validates_uniqueness_of :title
95
+ # end
96
+ #
97
+ # @param [ Array ] *args The arguments to pass to the validator.
98
+ def validates_uniqueness_of(*args)
99
+ validates_with(UniquenessValidator, _merge_attributes(args))
100
+ end
101
+
102
+ protected
103
+
104
+ # Adds an associated validator for the relation if the validate option
105
+ # was not provided or set to true.
106
+ #
107
+ # @example Set up validation.
108
+ # Person.validates_relation(metadata)
109
+ #
110
+ # @param [ Metadata ] metadata The relation metadata.
111
+ #
112
+ # @since 2.0.0.rc.1
113
+ def validates_relation(metadata)
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
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,44 @@
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
+ document.validated = true
31
+ valid = Array.wrap(value).collect do |doc|
32
+ if doc.nil?
33
+ true
34
+ else
35
+ doc.validated? ? true : doc.valid?
36
+ end
37
+ end.all?
38
+ document.validated = false
39
+ return if valid
40
+ document.errors.add(attribute, :invalid, options.merge(:value => value))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,58 @@
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. Will *not* load associations if
7
+ # they aren't already in memory.
8
+ #
9
+ # @example Set up the association validations.
10
+ #
11
+ # class Person
12
+ # include Mongoid::Document
13
+ # references_many :posts, :validate => true
14
+ # end
15
+ class ReferencedValidator < ActiveModel::EachValidator
16
+
17
+ # Validate the document for the initialized attributes. Will not load
18
+ # any association that's not currently loaded.
19
+ #
20
+ # @param [ Document ] document The document to validate.
21
+ def validate(document)
22
+ attributes.each do |attribute|
23
+ value = document.instance_variable_get("@#{attribute}".to_sym)
24
+ validate_each(document, attribute, value)
25
+ end
26
+ end
27
+
28
+ # Validates that the already loaded associations provided are either all
29
+ # nil or unchanged or all valid. If neither is true then the appropriate
30
+ # errors will be added to the parent document.
31
+ #
32
+ # @example Validate the loaded association.
33
+ # validator.validate_each(document, :name, name)
34
+ #
35
+ # @param [ Document ] document The document to validate.
36
+ # @param [ Symbol ] attribute The relation to validate.
37
+ # @param [ Object ] value The value of the relation.
38
+ def validate_each(document, attribute, value)
39
+ document.validated = true
40
+ valid =
41
+ if !value || !value.target
42
+ true
43
+ else
44
+ Array.wrap(value).collect do |doc|
45
+ if doc.nil? || (!doc.changed? && !doc.new_record?)
46
+ true
47
+ else
48
+ doc.validated? ? true : doc.valid?
49
+ end
50
+ end.all?
51
+ end
52
+ document.validated = false
53
+ return if valid
54
+ document.errors.add(attribute, :invalid, options.merge(:value => value))
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,85 @@
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
+
18
+ # Unfortunately, we have to tie Uniqueness validators to a class.
19
+ def setup(klass)
20
+ @klass = klass
21
+ end
22
+
23
+ # Validate the document for uniqueness violations.
24
+ #
25
+ # @example Validate the document.
26
+ # validate_each(person, :title, "Sir")
27
+ #
28
+ # @param [ Document ] document The document to validate.
29
+ # @param [ Symbol ] attribute The field to validate on.
30
+ # @param [ Object ] value The value of the field.
31
+ #
32
+ # @todo Durran: This method needs refactoring.
33
+ def validate_each(document, attribute, value)
34
+ if document.embedded?
35
+ return if document._parent.nil?
36
+ criteria = document._parent.send(document.metadata.name)
37
+ # If the parent document embeds_one, no need to validate uniqueness
38
+ return if criteria.is_a?(Mongoid::Document)
39
+ criteria = criteria.where(attribute => unique_search_value(value), :_id => {'$ne' => document._id})
40
+ else
41
+ criteria = @klass.where(attribute => unique_search_value(value))
42
+ unless document.new_record?
43
+ criteria = criteria.where(:_id => {'$ne' => document._id})
44
+ end
45
+ end
46
+
47
+ Array.wrap(options[:scope]).each do |item|
48
+ criteria = criteria.where(item => document.attributes[item.to_s])
49
+ end
50
+ if criteria.exists?
51
+ document.errors.add(
52
+ attribute,
53
+ :taken,
54
+ options.except(:case_sensitive, :scope).merge(:value => value)
55
+ )
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ # Determine if the primary key has changed on the document.
62
+ #
63
+ # @example Has the key changed?
64
+ # key_changed?(document)
65
+ #
66
+ # @param [ Document ] document The document to check.
67
+ #
68
+ # @return [ true, false ] True if changed, false if not.
69
+ def key_changed?(document)
70
+ (document.primary_key || {}).each do |key|
71
+ return true if document.send("#{key}_changed?")
72
+ end; false
73
+ end
74
+
75
+ # ensure :case_sensitive is true by default
76
+ def unique_search_value(value)
77
+ if options[:case_sensitive] == false
78
+ value ? Regexp.new("^#{Regexp.escape(value.to_s)}$", Regexp::IGNORECASE) : nil
79
+ else
80
+ value
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end