mongoid-locomotive 2.0.0.beta9

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 (274) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.rdoc +47 -0
  3. data/lib/mongoid.rb +141 -0
  4. data/lib/mongoid/associations.rb +306 -0
  5. data/lib/mongoid/associations/embedded_in.rb +74 -0
  6. data/lib/mongoid/associations/embeds_many.rb +280 -0
  7. data/lib/mongoid/associations/embeds_one.rb +97 -0
  8. data/lib/mongoid/associations/foreign_key.rb +35 -0
  9. data/lib/mongoid/associations/meta_data.rb +38 -0
  10. data/lib/mongoid/associations/options.rb +62 -0
  11. data/lib/mongoid/associations/proxy.rb +33 -0
  12. data/lib/mongoid/associations/referenced_in.rb +59 -0
  13. data/lib/mongoid/associations/references_many.rb +245 -0
  14. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  15. data/lib/mongoid/associations/references_one.rb +99 -0
  16. data/lib/mongoid/atomicity.rb +55 -0
  17. data/lib/mongoid/attributes.rb +242 -0
  18. data/lib/mongoid/callbacks.rb +21 -0
  19. data/lib/mongoid/collection.rb +120 -0
  20. data/lib/mongoid/collections.rb +71 -0
  21. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  22. data/lib/mongoid/collections/master.rb +29 -0
  23. data/lib/mongoid/collections/operations.rb +41 -0
  24. data/lib/mongoid/collections/slaves.rb +45 -0
  25. data/lib/mongoid/components.rb +34 -0
  26. data/lib/mongoid/config.rb +263 -0
  27. data/lib/mongoid/contexts.rb +24 -0
  28. data/lib/mongoid/contexts/enumerable.rb +156 -0
  29. data/lib/mongoid/contexts/ids.rb +25 -0
  30. data/lib/mongoid/contexts/mongo.rb +285 -0
  31. data/lib/mongoid/contexts/paging.rb +50 -0
  32. data/lib/mongoid/criteria.rb +248 -0
  33. data/lib/mongoid/criterion/complex.rb +21 -0
  34. data/lib/mongoid/criterion/exclusion.rb +65 -0
  35. data/lib/mongoid/criterion/inclusion.rb +110 -0
  36. data/lib/mongoid/criterion/optional.rb +189 -0
  37. data/lib/mongoid/cursor.rb +81 -0
  38. data/lib/mongoid/deprecation.rb +21 -0
  39. data/lib/mongoid/dirty.rb +252 -0
  40. data/lib/mongoid/document.rb +210 -0
  41. data/lib/mongoid/errors.rb +131 -0
  42. data/lib/mongoid/extensions.rb +115 -0
  43. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  44. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  45. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  46. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  47. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  48. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  49. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  50. data/lib/mongoid/extensions/date/conversions.rb +24 -0
  51. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  52. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  53. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  54. data/lib/mongoid/extensions/hash/accessors.rb +42 -0
  55. data/lib/mongoid/extensions/hash/assimilation.rb +40 -0
  56. data/lib/mongoid/extensions/hash/conversions.rb +42 -0
  57. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  58. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  59. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  60. data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
  61. data/lib/mongoid/extensions/object/conversions.rb +21 -0
  62. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  63. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  64. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  65. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  66. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  67. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  68. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  69. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  70. data/lib/mongoid/extras.rb +61 -0
  71. data/lib/mongoid/factory.rb +20 -0
  72. data/lib/mongoid/field.rb +83 -0
  73. data/lib/mongoid/fields.rb +62 -0
  74. data/lib/mongoid/finders.rb +145 -0
  75. data/lib/mongoid/hierarchy.rb +74 -0
  76. data/lib/mongoid/identity.rb +47 -0
  77. data/lib/mongoid/indexes.rb +27 -0
  78. data/lib/mongoid/javascript.rb +21 -0
  79. data/lib/mongoid/javascript/functions.yml +37 -0
  80. data/lib/mongoid/logger.rb +19 -0
  81. data/lib/mongoid/matchers.rb +35 -0
  82. data/lib/mongoid/matchers/all.rb +11 -0
  83. data/lib/mongoid/matchers/default.rb +26 -0
  84. data/lib/mongoid/matchers/exists.rb +13 -0
  85. data/lib/mongoid/matchers/gt.rb +11 -0
  86. data/lib/mongoid/matchers/gte.rb +11 -0
  87. data/lib/mongoid/matchers/in.rb +11 -0
  88. data/lib/mongoid/matchers/lt.rb +11 -0
  89. data/lib/mongoid/matchers/lte.rb +11 -0
  90. data/lib/mongoid/matchers/ne.rb +11 -0
  91. data/lib/mongoid/matchers/nin.rb +11 -0
  92. data/lib/mongoid/matchers/size.rb +11 -0
  93. data/lib/mongoid/memoization.rb +33 -0
  94. data/lib/mongoid/named_scope.rb +37 -0
  95. data/lib/mongoid/paranoia.rb +106 -0
  96. data/lib/mongoid/paths.rb +61 -0
  97. data/lib/mongoid/persistence.rb +216 -0
  98. data/lib/mongoid/persistence/command.rb +39 -0
  99. data/lib/mongoid/persistence/insert.rb +48 -0
  100. data/lib/mongoid/persistence/insert_embedded.rb +44 -0
  101. data/lib/mongoid/persistence/remove.rb +39 -0
  102. data/lib/mongoid/persistence/remove_all.rb +38 -0
  103. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  104. data/lib/mongoid/persistence/update.rb +71 -0
  105. data/lib/mongoid/railtie.rb +67 -0
  106. data/lib/mongoid/railties/database.rake +60 -0
  107. data/lib/mongoid/scope.rb +75 -0
  108. data/lib/mongoid/state.rb +32 -0
  109. data/lib/mongoid/timestamps.rb +27 -0
  110. data/lib/mongoid/validations.rb +51 -0
  111. data/lib/mongoid/validations/associated.rb +32 -0
  112. data/lib/mongoid/validations/locale/en.yml +5 -0
  113. data/lib/mongoid/validations/uniqueness.rb +56 -0
  114. data/lib/mongoid/version.rb +4 -0
  115. data/lib/mongoid/versioning.rb +26 -0
  116. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  117. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  118. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  119. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  120. data/lib/rails/generators/mongoid_generator.rb +61 -0
  121. data/spec/integration/mongoid/association_attributes_spec.rb +71 -0
  122. data/spec/integration/mongoid/associations_spec.rb +768 -0
  123. data/spec/integration/mongoid/attributes_spec.rb +59 -0
  124. data/spec/integration/mongoid/callback_spec.rb +33 -0
  125. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  126. data/spec/integration/mongoid/criteria_spec.rb +281 -0
  127. data/spec/integration/mongoid/dirty_spec.rb +85 -0
  128. data/spec/integration/mongoid/document_spec.rb +741 -0
  129. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  130. data/spec/integration/mongoid/finders_spec.rb +119 -0
  131. data/spec/integration/mongoid/inheritance_spec.rb +171 -0
  132. data/spec/integration/mongoid/named_scope_spec.rb +58 -0
  133. data/spec/integration/mongoid/paranoia_spec.rb +44 -0
  134. data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
  135. data/spec/integration/mongoid/persistence_spec.rb +311 -0
  136. data/spec/integration/mongoid/validations/uniqueness_spec.rb +206 -0
  137. data/spec/models/account.rb +5 -0
  138. data/spec/models/address.rb +40 -0
  139. data/spec/models/agent.rb +7 -0
  140. data/spec/models/animal.rb +15 -0
  141. data/spec/models/answer.rb +4 -0
  142. data/spec/models/callbacks.rb +47 -0
  143. data/spec/models/category.rb +13 -0
  144. data/spec/models/comment.rb +10 -0
  145. data/spec/models/country_code.rb +6 -0
  146. data/spec/models/employer.rb +5 -0
  147. data/spec/models/favorite.rb +8 -0
  148. data/spec/models/game.rb +9 -0
  149. data/spec/models/inheritance.rb +72 -0
  150. data/spec/models/location.rb +5 -0
  151. data/spec/models/login.rb +6 -0
  152. data/spec/models/mixed_drink.rb +4 -0
  153. data/spec/models/name.rb +13 -0
  154. data/spec/models/namespacing.rb +11 -0
  155. data/spec/models/paranoid_post.rb +18 -0
  156. data/spec/models/parents.rb +32 -0
  157. data/spec/models/patient.rb +15 -0
  158. data/spec/models/person.rb +106 -0
  159. data/spec/models/pet.rb +7 -0
  160. data/spec/models/pet_owner.rb +6 -0
  161. data/spec/models/phone.rb +7 -0
  162. data/spec/models/post.rb +25 -0
  163. data/spec/models/preference.rb +7 -0
  164. data/spec/models/question.rb +8 -0
  165. data/spec/models/survey.rb +6 -0
  166. data/spec/models/translation.rb +5 -0
  167. data/spec/models/user.rb +6 -0
  168. data/spec/models/user_accout.rb +5 -0
  169. data/spec/models/vet_visit.rb +5 -0
  170. data/spec/models/video.rb +5 -0
  171. data/spec/spec_helper.rb +33 -0
  172. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  173. data/spec/unit/mongoid/associations/embeds_many_spec.rb +626 -0
  174. data/spec/unit/mongoid/associations/embeds_one_spec.rb +287 -0
  175. data/spec/unit/mongoid/associations/foreign_key_spec.rb +90 -0
  176. data/spec/unit/mongoid/associations/meta_data_spec.rb +110 -0
  177. data/spec/unit/mongoid/associations/options_spec.rb +215 -0
  178. data/spec/unit/mongoid/associations/referenced_in_spec.rb +145 -0
  179. data/spec/unit/mongoid/associations/references_many_as_array_spec.rb +424 -0
  180. data/spec/unit/mongoid/associations/references_many_spec.rb +502 -0
  181. data/spec/unit/mongoid/associations/references_one_spec.rb +204 -0
  182. data/spec/unit/mongoid/associations_spec.rb +688 -0
  183. data/spec/unit/mongoid/atomicity_spec.rb +164 -0
  184. data/spec/unit/mongoid/attributes_spec.rb +646 -0
  185. data/spec/unit/mongoid/callbacks_spec.rb +85 -0
  186. data/spec/unit/mongoid/collection_spec.rb +187 -0
  187. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  188. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  189. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  190. data/spec/unit/mongoid/collections_spec.rb +98 -0
  191. data/spec/unit/mongoid/config_spec.rb +298 -0
  192. data/spec/unit/mongoid/contexts/enumerable_spec.rb +447 -0
  193. data/spec/unit/mongoid/contexts/mongo_spec.rb +703 -0
  194. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  195. data/spec/unit/mongoid/criteria_spec.rb +873 -0
  196. data/spec/unit/mongoid/criterion/complex_spec.rb +17 -0
  197. data/spec/unit/mongoid/criterion/exclusion_spec.rb +121 -0
  198. data/spec/unit/mongoid/criterion/inclusion_spec.rb +274 -0
  199. data/spec/unit/mongoid/criterion/optional_spec.rb +483 -0
  200. data/spec/unit/mongoid/cursor_spec.rb +80 -0
  201. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  202. data/spec/unit/mongoid/dirty_spec.rb +430 -0
  203. data/spec/unit/mongoid/document_spec.rb +623 -0
  204. data/spec/unit/mongoid/errors_spec.rb +154 -0
  205. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  206. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  207. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +52 -0
  208. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  209. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +36 -0
  210. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  211. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  212. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +145 -0
  213. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +14 -0
  214. data/spec/unit/mongoid/extensions/false_class/equality_spec.rb +35 -0
  215. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  216. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  217. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +59 -0
  218. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +35 -0
  219. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  220. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  221. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  222. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +29 -0
  223. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +44 -0
  224. data/spec/unit/mongoid/extensions/objectid/conversions_spec.rb +22 -0
  225. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  226. data/spec/unit/mongoid/extensions/set/conversions_spec.rb +21 -0
  227. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +28 -0
  228. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  229. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +107 -0
  230. data/spec/unit/mongoid/extensions/time_conversions_spec.rb +186 -0
  231. data/spec/unit/mongoid/extensions/true_class/equality_spec.rb +35 -0
  232. data/spec/unit/mongoid/extras_spec.rb +102 -0
  233. data/spec/unit/mongoid/factory_spec.rb +31 -0
  234. data/spec/unit/mongoid/field_spec.rb +169 -0
  235. data/spec/unit/mongoid/fields_spec.rb +181 -0
  236. data/spec/unit/mongoid/finders_spec.rb +439 -0
  237. data/spec/unit/mongoid/hierarchy_spec.rb +68 -0
  238. data/spec/unit/mongoid/identity_spec.rb +109 -0
  239. data/spec/unit/mongoid/indexes_spec.rb +99 -0
  240. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  241. data/spec/unit/mongoid/logger_spec.rb +38 -0
  242. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  243. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  244. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  245. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  246. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  247. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  248. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  249. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  250. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  251. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  252. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  253. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  254. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  255. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  256. data/spec/unit/mongoid/paranoia_spec.rb +108 -0
  257. data/spec/unit/mongoid/paths_spec.rb +272 -0
  258. data/spec/unit/mongoid/persistence/insert_embedded_spec.rb +154 -0
  259. data/spec/unit/mongoid/persistence/insert_spec.rb +144 -0
  260. data/spec/unit/mongoid/persistence/remove_all_spec.rb +82 -0
  261. data/spec/unit/mongoid/persistence/remove_embedded_spec.rb +152 -0
  262. data/spec/unit/mongoid/persistence/remove_spec.rb +89 -0
  263. data/spec/unit/mongoid/persistence/update_spec.rb +177 -0
  264. data/spec/unit/mongoid/persistence_spec.rb +452 -0
  265. data/spec/unit/mongoid/scope_spec.rb +240 -0
  266. data/spec/unit/mongoid/serialization_spec.rb +43 -0
  267. data/spec/unit/mongoid/state_spec.rb +94 -0
  268. data/spec/unit/mongoid/timestamps_spec.rb +30 -0
  269. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  270. data/spec/unit/mongoid/validations/uniqueness_spec.rb +201 -0
  271. data/spec/unit/mongoid/validations_spec.rb +43 -0
  272. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  273. data/spec/unit/mongoid_spec.rb +46 -0
  274. metadata +433 -0
@@ -0,0 +1,311 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Persistence do
4
+
5
+ before do
6
+ @person = Person.new(:title => "Sir", :ssn => "6969696", :pets => true)
7
+ end
8
+
9
+ after do
10
+ @person.delete
11
+ end
12
+
13
+ describe ".create" do
14
+
15
+ it "saves and returns the document" do
16
+ person = Person.create(:title => "Sensei", :ssn => "666-66-6666")
17
+ person.should be_a_kind_of(Person)
18
+ person.should_not be_a_new_record
19
+ end
20
+ end
21
+
22
+ describe ".create!" do
23
+
24
+ context "inserting with a field that is not unique" do
25
+
26
+ context "when a unique index exists" do
27
+
28
+ after do
29
+ Person.delete_all
30
+ end
31
+
32
+ it "raises an error" do
33
+ Person.create!(:ssn => "555-55-9999")
34
+ lambda { Person.create!(:ssn => "555-55-9999") }.should raise_error
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#delete" do
41
+
42
+ context "deleting a root document" do
43
+
44
+ before do
45
+ @person.save
46
+ end
47
+
48
+ it "deletes the document" do
49
+ @person.delete
50
+ lambda { Person.find(@person.id) }.should raise_error
51
+ end
52
+
53
+ it "returns true" do
54
+ @person.delete.should be_true
55
+ end
56
+ end
57
+
58
+ context "deleting an embedded document" do
59
+
60
+ before do
61
+ @address = Address.new(:street => "Bond Street")
62
+ @person.addresses << @address
63
+ end
64
+
65
+ context "when the document is not yet saved" do
66
+
67
+ it "removes the document from the parent" do
68
+ @address.delete
69
+ @person.addresses.should be_empty
70
+ @person.attributes[:addresses].should be_empty
71
+ end
72
+ end
73
+
74
+ context "when the document has been saved" do
75
+
76
+ before do
77
+ @address.save
78
+ end
79
+
80
+ it "removes the object from the parent and database" do
81
+ @address.delete
82
+ from_db = Person.find(@person.id)
83
+ from_db.addresses.should be_empty
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "#destroy" do
90
+
91
+ context "destroying a root document" do
92
+
93
+ before do
94
+ @person.save
95
+ end
96
+
97
+ it "destroys the document" do
98
+ @person.destroy
99
+ lambda { Person.find(@person.id) }.should raise_error
100
+ end
101
+
102
+ it "returns true" do
103
+ @person.destroy.should be_true
104
+ end
105
+ end
106
+
107
+ context "deleting an embedded document" do
108
+
109
+ before do
110
+ @address = Address.new(:street => "Bond Street", :city => "London", :country => "UK")
111
+ @person.addresses << @address
112
+ end
113
+
114
+ context "when the document is not yet saved" do
115
+
116
+ it "removes the document from the parent" do
117
+ @address.delete
118
+ @person.addresses.should be_empty
119
+ @person.attributes[:addresses].should be_empty
120
+ end
121
+ end
122
+
123
+ context "when the document has been saved" do
124
+
125
+ before do
126
+ @address.save
127
+ end
128
+
129
+ it "removes the object from the parent and database" do
130
+ @address.delete
131
+ from_db = Person.find(@person.id)
132
+ from_db.addresses.should be_empty
133
+ end
134
+ end
135
+ end
136
+
137
+ context "deleting deeply embedded documents" do
138
+
139
+ before do
140
+ @address = Address.new(:street => "Bond Street", :city => "London", :country => "UK")
141
+ @person.addresses << @address
142
+ end
143
+
144
+ context "when the document has been saved" do
145
+
146
+ before do
147
+ @address.save
148
+ @location = Location.new(:name => "Home")
149
+ @address.locations << @location
150
+ @location.save
151
+ end
152
+
153
+ it "removes the object from the parent and database" do
154
+ @location.delete
155
+ from_db = Person.find(@person.id)
156
+ from_db.addresses.first.locations.should be_empty
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ describe "#save" do
163
+
164
+ context "when validation passes" do
165
+
166
+ it "returns true" do
167
+ @person.save.should be_true
168
+ end
169
+ end
170
+
171
+ context "when validation fails" do
172
+
173
+ before do
174
+ @address = @person.addresses.create(:city => "London")
175
+ end
176
+
177
+ it "returns false" do
178
+ @address.save.should == false
179
+ end
180
+
181
+ it "has the appropriate errors" do
182
+ @address.save
183
+ @address.errors[:street].should == ["can't be blank"]
184
+ end
185
+ end
186
+
187
+ context "when modifying the entire hierarchy" do
188
+
189
+ context "when performing modification and insert ops" do
190
+
191
+ before do
192
+ @person = Person.create(:title => "Blah", :ssn => "244-01-1112")
193
+ @person.title = "King"
194
+ @address = @person.addresses.build(:street => "Bond St")
195
+ @person.create_name(:first_name => "Tony")
196
+ @person.name.first_name = "Ryan"
197
+ end
198
+
199
+ it "saves the hierarchy" do
200
+ @person.save
201
+ @person.reload
202
+ @person.title.should == "King"
203
+ @person.name.first_name.should == "Ryan"
204
+ @person.addresses.first.street.should == "Bond St"
205
+ end
206
+
207
+ it "persists with proper set and push modifiers" do
208
+ @person._updates.should == {
209
+ "$set" => { "title" => "King", "name.first_name" => "Ryan" },
210
+ "$pushAll"=> { "addresses" => [{ "_id" => @address.id, "street"=>"Bond St" }]}
211
+ }
212
+ @person.save
213
+ @person._updates.should == {}
214
+ end
215
+
216
+ end
217
+
218
+ context "when removing elements without using delete or destroy" do
219
+
220
+ before do
221
+ @person = Person.create(:title => "Blah", :ssn => "244-01-1112")
222
+ @person.create_name(:first_name => "Tony")
223
+ @person.name = nil
224
+ end
225
+
226
+ it "saves the hierarchy" do
227
+ @person.save
228
+ @person.reload
229
+ @person.name.should be_nil
230
+ end
231
+
232
+ it "persists with proper unset and pull modifiers" do
233
+ @person._updates.should == {
234
+ "$set" => { "name" => nil }
235
+ }
236
+ @person.save
237
+ @person._updates.should == {}
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ describe "save!" do
244
+
245
+ context "inserting with a field that is not unique" do
246
+
247
+ context "when a unique index exists" do
248
+
249
+ it "raises an error" do
250
+ Person.create!(:ssn => "555-55-9999")
251
+ person = Person.new(:ssn => "555-55-9999")
252
+ lambda { person.save!(:ssn => "555-55-9999") }.should raise_error
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ describe "#update_attributes" do
259
+
260
+ before do
261
+ @person.save
262
+ end
263
+
264
+ context "when validation passes" do
265
+
266
+ it "returns true" do
267
+ @person.update_attributes(:ssn => "555-55-1234").should be_true
268
+ end
269
+
270
+ it "saves the attributes" do
271
+ @person.update_attributes(:ssn => "555-55-1235", :pets => false, :title => nil)
272
+ @from_db = Person.find(@person.id)
273
+ @from_db.ssn.should == "555-55-1235"
274
+ @from_db.pets.should == false
275
+ @from_db.title.should be_nil
276
+ end
277
+ end
278
+ end
279
+
280
+ describe "#delete_all" do
281
+
282
+ before do
283
+ @person.save
284
+ end
285
+
286
+ it "deletes all the documents" do
287
+ Person.delete_all
288
+ Person.count.should == 0
289
+ end
290
+
291
+ it "returns the number of documents deleted" do
292
+ Person.delete_all.should == 1
293
+ end
294
+ end
295
+
296
+ describe "#destroy_all" do
297
+
298
+ before do
299
+ @person.save
300
+ end
301
+
302
+ it "destroys all the documents" do
303
+ Person.destroy_all
304
+ Person.count.should == 0
305
+ end
306
+
307
+ it "returns the number of documents destroyed" do
308
+ Person.destroy_all.should == 1
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,206 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Validations::UniquenessValidator do
4
+
5
+ before do
6
+ UserAccount.delete_all
7
+ Login.delete_all
8
+ Person.delete_all
9
+ Patient.delete_all
10
+ end
11
+
12
+ after do
13
+ UserAccount.delete_all
14
+ Login.delete_all
15
+ Person.delete_all
16
+ Patient.delete_all
17
+ end
18
+
19
+ context "when the document has no composite keys defined" do
20
+
21
+ context "when no record in the database" do
22
+
23
+ let(:account) do
24
+ UserAccount.new(:username => "rdawkins")
25
+ end
26
+
27
+ it "passes validation" do
28
+ account.should be_valid
29
+ end
30
+ end
31
+
32
+ context "with a record in the database" do
33
+
34
+ before do
35
+ UserAccount.create(:username => "chitchins")
36
+ UserAccount.create(:username => "rdawkins")
37
+ end
38
+
39
+ context "when document is not new" do
40
+
41
+ let(:account) do
42
+ UserAccount.where(:username => "rdawkins").first
43
+ end
44
+
45
+ it "passes validation" do
46
+ account.should be_valid
47
+ end
48
+
49
+ it "fails validation when another document has the same unique field" do
50
+ account.username = "chitchins"
51
+ account.should_not be_valid
52
+ end
53
+ end
54
+
55
+ context "when document is new" do
56
+
57
+ let(:account) do
58
+ UserAccount.new(:username => "rdawkins")
59
+ end
60
+
61
+ it "fails validation" do
62
+ account.should_not be_valid
63
+ end
64
+
65
+ it "contains uniqueness errors" do
66
+ account.valid?
67
+ account.errors[:username].should == ["is not unique"]
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context "when the document has keys defined" do
74
+
75
+ context "when no record in the database" do
76
+
77
+ let(:login) do
78
+ Login.new(:username => "rdawkins")
79
+ end
80
+
81
+ it "passes validation" do
82
+ login.should be_valid
83
+ end
84
+ end
85
+
86
+ context "with a record in the database" do
87
+
88
+ before do
89
+ Login.create(:username => "rdawkins")
90
+ end
91
+
92
+ context "when the document is new" do
93
+
94
+ let(:login) do
95
+ Login.new(:username => "rdawkins")
96
+ end
97
+
98
+ it "fails validation" do
99
+ login.should_not be_valid
100
+ end
101
+
102
+ it "contains uniqueness errors" do
103
+ login.valid?
104
+ login.errors[:username].should == ["is already taken"]
105
+ end
106
+ end
107
+
108
+ context "when the document is not new" do
109
+
110
+ before do
111
+ Login.create(:username => "chitchins")
112
+ Login.create(:username => "rdawkins")
113
+ end
114
+
115
+ context "when the key has changed" do
116
+
117
+ let(:login) do
118
+ Login.where(:username => "chitchins").first
119
+ end
120
+
121
+ before do
122
+ login.username = "rdawkins"
123
+ end
124
+
125
+ it "fails validation" do
126
+ login.should_not be_valid
127
+ end
128
+ end
129
+
130
+ context "when the key has not changed" do
131
+
132
+ let(:login) do
133
+ Login.where(:username => "rdawkins").first
134
+ end
135
+
136
+ it "passes validation" do
137
+ login.should be_valid
138
+ end
139
+ end
140
+
141
+ end
142
+ end
143
+ end
144
+
145
+ context "when the parent document embeds_many" do
146
+ let(:person) { Person.create }
147
+ context "when no record in the database" do
148
+ let(:favorite) { person.favorites.build(:title => "pizza") }
149
+
150
+ it "passes validation" do
151
+ favorite.should be_valid
152
+ end
153
+ end
154
+
155
+ context "with a record in the database" do
156
+ before do
157
+ person.favorites.create(:title => "pizza")
158
+ person.favorites.create(:title => "doritos")
159
+ end
160
+
161
+ context "when document is not new" do
162
+ let(:favorite) { person.favorites.where(:title => "pizza").first }
163
+
164
+ it "passes validation" do
165
+ favorite.should be_valid
166
+ end
167
+
168
+ it "fails validation when another document has the same unique field" do
169
+ favorite.title = "doritos"
170
+ favorite.should_not be_valid
171
+ end
172
+ end
173
+
174
+ context "when document is new" do
175
+ let(:favorite) { person.favorites.build(:title => "pizza") }
176
+
177
+ it "fails validation" do
178
+ favorite.should_not be_valid
179
+ end
180
+
181
+ it "contains uniqueness errors" do
182
+ favorite.valid?
183
+ favorite.errors[:title].should == ["is already taken"]
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ context "when the parent document embeds_one" do
190
+ let(:patient) { Patient.create }
191
+ let(:email) { Email.new(:address => "joe@example.com", :patient => patient) }
192
+
193
+ it "passes validation" do
194
+ email.should be_valid
195
+ end
196
+
197
+ context "when replacing with a new record with the same value" do
198
+ before do
199
+ Email.create(:address => "joe@example.com", :patient => patient)
200
+ end
201
+ it "passes validation" do
202
+ email.should be_valid
203
+ end
204
+ end
205
+ end
206
+ end