mongoid 1.9.5 → 2.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. data/.gitignore +6 -0
  2. data/.watchr +29 -0
  3. data/Rakefile +52 -0
  4. data/VERSION +1 -0
  5. data/caliper.yml +4 -0
  6. data/lib/mongoid.rb +20 -9
  7. data/lib/mongoid/associations.rb +100 -123
  8. data/lib/mongoid/associations/belongs_to_related.rb +3 -2
  9. data/lib/mongoid/associations/{embeds_many.rb → embed_many.rb} +29 -90
  10. data/lib/mongoid/associations/{embeds_one.rb → embed_one.rb} +7 -8
  11. data/lib/mongoid/associations/embedded_in.rb +4 -12
  12. data/lib/mongoid/associations/has_many_related.rb +4 -52
  13. data/lib/mongoid/associations/has_one_related.rb +4 -8
  14. data/lib/mongoid/associations/meta_data.rb +1 -2
  15. data/lib/mongoid/associations/options.rb +1 -6
  16. data/lib/mongoid/associations/proxy.rb +21 -14
  17. data/lib/mongoid/attributes.rb +13 -33
  18. data/lib/mongoid/callbacks.rb +11 -16
  19. data/lib/mongoid/collection.rb +3 -4
  20. data/lib/mongoid/collections/master.rb +2 -3
  21. data/lib/mongoid/collections/mimic.rb +46 -0
  22. data/lib/mongoid/collections/slaves.rb +2 -3
  23. data/lib/mongoid/commands.rb +161 -0
  24. data/lib/mongoid/commands/create.rb +19 -0
  25. data/lib/mongoid/commands/delete.rb +16 -0
  26. data/lib/mongoid/commands/delete_all.rb +23 -0
  27. data/lib/mongoid/commands/deletion.rb +18 -0
  28. data/lib/mongoid/commands/destroy.rb +17 -0
  29. data/lib/mongoid/commands/destroy_all.rb +23 -0
  30. data/lib/mongoid/commands/save.rb +29 -0
  31. data/lib/mongoid/components.rb +6 -4
  32. data/lib/mongoid/config.rb +15 -134
  33. data/lib/mongoid/contexts.rb +1 -1
  34. data/lib/mongoid/contexts/enumerable.rb +1 -1
  35. data/lib/mongoid/contexts/mongo.rb +1 -1
  36. data/lib/mongoid/contexts/paging.rb +2 -10
  37. data/lib/mongoid/criterion/inclusion.rb +0 -17
  38. data/lib/mongoid/criterion/optional.rb +1 -1
  39. data/lib/mongoid/cursor.rb +1 -0
  40. data/lib/mongoid/document.rb +45 -49
  41. data/lib/mongoid/errors.rb +1 -32
  42. data/lib/mongoid/extensions.rb +10 -12
  43. data/lib/mongoid/extensions/array/conversions.rb +6 -8
  44. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  45. data/lib/mongoid/extensions/boolean/conversions.rb +2 -8
  46. data/lib/mongoid/extensions/date/conversions.rb +4 -13
  47. data/lib/mongoid/extensions/datetime/conversions.rb +6 -1
  48. data/lib/mongoid/extensions/float/conversions.rb +1 -5
  49. data/lib/mongoid/extensions/hash/assimilation.rb +3 -12
  50. data/lib/mongoid/extensions/hash/conversions.rb +4 -34
  51. data/lib/mongoid/extensions/integer/conversions.rb +1 -5
  52. data/lib/mongoid/extensions/nil/assimilation.rb +0 -4
  53. data/lib/mongoid/extensions/object/conversions.rb +2 -8
  54. data/lib/mongoid/extensions/objectid/conversions.rb +1 -1
  55. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  56. data/lib/mongoid/extensions/symbol/inflections.rb +1 -1
  57. data/lib/mongoid/extensions/time/conversions.rb +18 -0
  58. data/lib/mongoid/factory.rb +1 -2
  59. data/lib/mongoid/field.rb +2 -9
  60. data/lib/mongoid/fields.rb +7 -11
  61. data/lib/mongoid/finders.rb +2 -2
  62. data/lib/mongoid/identity.rb +4 -4
  63. data/lib/mongoid/indexes.rb +7 -10
  64. data/lib/mongoid/memoization.rb +2 -8
  65. data/lib/mongoid/named_scope.rb +5 -0
  66. data/lib/mongoid/observable.rb +1 -1
  67. data/lib/mongoid/paths.rb +22 -30
  68. data/lib/mongoid/state.rb +21 -28
  69. data/lib/mongoid/timestamps.rb +1 -1
  70. data/lib/mongoid/validations.rb +51 -0
  71. data/lib/mongoid/validations/associated.rb +32 -0
  72. data/lib/mongoid/validations/locale/en.yml +4 -0
  73. data/lib/mongoid/validations/uniqueness.rb +22 -0
  74. data/lib/mongoid/versioning.rb +1 -2
  75. data/mongoid.gemspec +408 -0
  76. data/perf/benchmark.rb +77 -0
  77. data/spec/integration/mongoid/associations_spec.rb +340 -0
  78. data/spec/integration/mongoid/attributes_spec.rb +22 -0
  79. data/spec/integration/mongoid/commands_spec.rb +227 -0
  80. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  81. data/spec/integration/mongoid/criteria_spec.rb +272 -0
  82. data/spec/integration/mongoid/document_spec.rb +650 -0
  83. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  84. data/spec/integration/mongoid/finders_spec.rb +119 -0
  85. data/spec/integration/mongoid/inheritance_spec.rb +137 -0
  86. data/spec/integration/mongoid/named_scope_spec.rb +46 -0
  87. data/spec/models/address.rb +39 -0
  88. data/spec/models/animal.rb +6 -0
  89. data/spec/models/callbacks.rb +18 -0
  90. data/spec/models/comment.rb +8 -0
  91. data/spec/models/country_code.rb +6 -0
  92. data/spec/models/employer.rb +5 -0
  93. data/spec/models/game.rb +7 -0
  94. data/spec/models/inheritance.rb +56 -0
  95. data/spec/models/location.rb +5 -0
  96. data/spec/models/mixed_drink.rb +4 -0
  97. data/spec/models/name.rb +13 -0
  98. data/spec/models/namespacing.rb +11 -0
  99. data/spec/models/patient.rb +4 -0
  100. data/spec/models/person.rb +99 -0
  101. data/spec/models/pet.rb +7 -0
  102. data/spec/models/pet_owner.rb +6 -0
  103. data/spec/models/phone.rb +7 -0
  104. data/spec/models/post.rb +15 -0
  105. data/spec/models/translation.rb +5 -0
  106. data/spec/models/vet_visit.rb +5 -0
  107. data/spec/spec.opts +3 -0
  108. data/spec/spec_helper.rb +31 -0
  109. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +145 -0
  110. data/spec/unit/mongoid/associations/embed_many_spec.rb +516 -0
  111. data/spec/unit/mongoid/associations/embed_one_spec.rb +282 -0
  112. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  113. data/spec/unit/mongoid/associations/has_many_related_spec.rb +418 -0
  114. data/spec/unit/mongoid/associations/has_one_related_spec.rb +179 -0
  115. data/spec/unit/mongoid/associations/meta_data_spec.rb +88 -0
  116. data/spec/unit/mongoid/associations/options_spec.rb +192 -0
  117. data/spec/unit/mongoid/associations_spec.rb +595 -0
  118. data/spec/unit/mongoid/attributes_spec.rb +507 -0
  119. data/spec/unit/mongoid/callbacks_spec.rb +55 -0
  120. data/spec/unit/mongoid/collection_spec.rb +187 -0
  121. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  122. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  123. data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
  124. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  125. data/spec/unit/mongoid/commands/create_spec.rb +31 -0
  126. data/spec/unit/mongoid/commands/delete_all_spec.rb +58 -0
  127. data/spec/unit/mongoid/commands/delete_spec.rb +38 -0
  128. data/spec/unit/mongoid/commands/destroy_all_spec.rb +21 -0
  129. data/spec/unit/mongoid/commands/destroy_spec.rb +51 -0
  130. data/spec/unit/mongoid/commands/save_spec.rb +107 -0
  131. data/spec/unit/mongoid/commands_spec.rb +270 -0
  132. data/spec/unit/mongoid/config_spec.rb +172 -0
  133. data/spec/unit/mongoid/contexts/enumerable_spec.rb +421 -0
  134. data/spec/unit/mongoid/contexts/mongo_spec.rb +682 -0
  135. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  136. data/spec/unit/mongoid/criteria_spec.rb +824 -0
  137. data/spec/unit/mongoid/criterion/complex_spec.rb +19 -0
  138. data/spec/unit/mongoid/criterion/exclusion_spec.rb +91 -0
  139. data/spec/unit/mongoid/criterion/inclusion_spec.rb +219 -0
  140. data/spec/unit/mongoid/criterion/optional_spec.rb +319 -0
  141. data/spec/unit/mongoid/cursor_spec.rb +74 -0
  142. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  143. data/spec/unit/mongoid/document_spec.rb +818 -0
  144. data/spec/unit/mongoid/errors_spec.rb +103 -0
  145. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  146. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  147. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +35 -0
  148. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  149. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +22 -0
  150. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  151. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  152. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +102 -0
  153. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +67 -0
  154. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  155. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  156. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +46 -0
  157. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +21 -0
  158. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  159. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  160. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  161. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +24 -0
  162. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +57 -0
  163. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  164. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +17 -0
  165. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  166. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +91 -0
  167. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +70 -0
  168. data/spec/unit/mongoid/extras_spec.rb +102 -0
  169. data/spec/unit/mongoid/factory_spec.rb +31 -0
  170. data/spec/unit/mongoid/field_spec.rb +143 -0
  171. data/spec/unit/mongoid/fields_spec.rb +181 -0
  172. data/spec/unit/mongoid/finders_spec.rb +404 -0
  173. data/spec/unit/mongoid/identity_spec.rb +109 -0
  174. data/spec/unit/mongoid/indexes_spec.rb +93 -0
  175. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  176. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  177. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  178. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  179. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  180. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  181. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  182. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  183. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  184. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  185. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  186. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  187. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  188. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  189. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  190. data/spec/unit/mongoid/observable_spec.rb +46 -0
  191. data/spec/unit/mongoid/paths_spec.rb +124 -0
  192. data/spec/unit/mongoid/scope_spec.rb +240 -0
  193. data/spec/unit/mongoid/state_spec.rb +83 -0
  194. data/spec/unit/mongoid/timestamps_spec.rb +25 -0
  195. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  196. data/spec/unit/mongoid/validations/uniqueness_spec.rb +47 -0
  197. data/spec/unit/mongoid/validations_spec.rb +190 -0
  198. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  199. data/spec/unit/mongoid_spec.rb +46 -0
  200. metadata +316 -110
  201. data/lib/mongoid/collections.rb +0 -41
  202. data/lib/mongoid/concern.rb +0 -31
  203. data/lib/mongoid/dirty.rb +0 -253
  204. data/lib/mongoid/extensions/time_conversions.rb +0 -35
  205. data/lib/mongoid/persistence.rb +0 -222
  206. data/lib/mongoid/persistence/command.rb +0 -39
  207. data/lib/mongoid/persistence/insert.rb +0 -50
  208. data/lib/mongoid/persistence/insert_embedded.rb +0 -38
  209. data/lib/mongoid/persistence/remove.rb +0 -39
  210. data/lib/mongoid/persistence/remove_all.rb +0 -37
  211. data/lib/mongoid/persistence/remove_embedded.rb +0 -50
  212. data/lib/mongoid/persistence/update.rb +0 -63
  213. data/lib/mongoid/version.rb +0 -4
@@ -0,0 +1,507 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Attributes do
4
+
5
+ describe ".accepts_nested_attributes_for" do
6
+
7
+ before do
8
+ @person = Person.new
9
+ end
10
+
11
+ it "adds a setter for the association attributes" do
12
+ @person.should respond_to(:addresses_attributes=)
13
+ end
14
+
15
+ describe "#association_attributes=" do
16
+
17
+ context "on a has many association" do
18
+
19
+ context "when a reject block supplied" do
20
+
21
+ before do
22
+ @attributes = {
23
+ "0" => { "city" => "San Francisco" }
24
+ }
25
+ @person.addresses_attributes = @attributes
26
+ end
27
+
28
+ it "removes the attributes that match" do
29
+ @person.addresses.should be_empty
30
+ end
31
+
32
+ end
33
+
34
+ context "when association is empty" do
35
+
36
+ before do
37
+ @attributes = {
38
+ "0" => { "street" => "Folsom", "city" => "San Francisco" }
39
+ }
40
+ @person.addresses_attributes = @attributes
41
+ end
42
+
43
+ it "adds a new document to the association" do
44
+ address = @person.addresses.first
45
+ address.street.should == "Folsom"
46
+ address.city.should == "San Francisco"
47
+ end
48
+
49
+ end
50
+
51
+ context "when association is not empty" do
52
+
53
+ before do
54
+ @person = Person.new
55
+ @person.addresses.build(:street => "Broadway", :city => "New York")
56
+ @attributes = {
57
+ "0" => { "street" => "Folsom", "city" => "San Francisco" }
58
+ }
59
+ @person.addresses_attributes = @attributes
60
+ end
61
+
62
+ it "updates the existing attributes on the association" do
63
+ @person.addresses.size.should == 2
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ context "on a has one association" do
71
+
72
+ before do
73
+ @person = Person.new
74
+ @attributes = {
75
+ "first_name" => "Fernando", "last_name" => "Torres"
76
+ }
77
+ @person.name_attributes = @attributes
78
+ end
79
+
80
+ it "replaces the document on the association" do
81
+ name = @person.name
82
+ name.first_name.should == "Fernando"
83
+ name.last_name.should == "Torres"
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ describe "#_id" do
93
+
94
+ before do
95
+ @person = Person.new
96
+ end
97
+
98
+ it "delegates to #id" do
99
+ @person._id.should == @person.id
100
+ end
101
+
102
+ end
103
+
104
+ describe "#_id=" do
105
+
106
+ before do
107
+ @person = Person.new
108
+ end
109
+
110
+ it "delegates to #id=" do
111
+ @id = Mongo::ObjectID.new.to_s
112
+ @person._id = @id
113
+ @person.id.should == @id
114
+ end
115
+
116
+ end
117
+
118
+ describe "#method_missing" do
119
+
120
+ before do
121
+ Mongoid.configure.allow_dynamic_fields = true
122
+ @attributes = {
123
+ :testing => "Testing"
124
+ }
125
+ @person = Person.new(@attributes)
126
+ end
127
+
128
+ context "when an attribute exists" do
129
+
130
+ it "allows the getter" do
131
+ @person.testing.should == "Testing"
132
+ end
133
+
134
+ it "allows the setter" do
135
+ @person.testing = "Test"
136
+ @person.testing.should == "Test"
137
+ end
138
+
139
+ end
140
+
141
+ end
142
+
143
+ describe "#process" do
144
+
145
+ context "when passing non accessible fields" do
146
+
147
+ before do
148
+ @person = Person.new(:owner_id => 6)
149
+ end
150
+
151
+ it "does not set the value" do
152
+ @person.owner_id.should be_nil
153
+ end
154
+ end
155
+
156
+ context "when attributes dont have fields defined" do
157
+
158
+ before do
159
+ @attributes = {
160
+ :nofieldstring => "Testing",
161
+ :nofieldint => 5,
162
+ :employer => Employer.new
163
+ }
164
+ end
165
+
166
+ context "when allowing dynamic fields" do
167
+
168
+ before do
169
+ Mongoid.configure.allow_dynamic_fields = true
170
+ @person = Person.new(@attributes)
171
+ end
172
+
173
+ context "when attribute is a string" do
174
+
175
+ it "adds the string to the attributes" do
176
+ @person.attributes[:nofieldstring].should == "Testing"
177
+ end
178
+
179
+ end
180
+
181
+ context "when attribute is not a string" do
182
+
183
+ it "adds a cast value to the attributes" do
184
+ @person.attributes[:nofieldint].should == 5
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+
191
+ context "when not allowing dynamic fields" do
192
+
193
+ before do
194
+ Mongoid.configure.allow_dynamic_fields = false
195
+ Person.fields.delete(:nofieldstring)
196
+ @attributes = {
197
+ :nofieldstring => "Testing"
198
+ }
199
+ end
200
+
201
+ after do
202
+ Mongoid.configure.allow_dynamic_fields = true
203
+ end
204
+
205
+ it "raises an error" do
206
+ lambda { Person.new(@attributes) }.should raise_error
207
+ end
208
+
209
+ end
210
+
211
+ end
212
+
213
+ context "when supplied hash has values" do
214
+
215
+ before do
216
+ @attributes = {
217
+ :_id => "1",
218
+ :title => "value",
219
+ :age => "30",
220
+ :terms => "true",
221
+ :score => "",
222
+ :name => {
223
+ :_id => "2", :first_name => "Test", :last_name => "User"
224
+ },
225
+ :addresses => [
226
+ { :_id => "3", :street => "First Street" },
227
+ { :_id => "4", :street => "Second Street" }
228
+ ]
229
+ }
230
+ end
231
+
232
+ it "returns properly cast attributes" do
233
+ attrs = Person.new(@attributes).attributes
234
+ attrs[:age].should == 30
235
+ attrs[:terms].should == true
236
+ attrs[:_id].should == "1"
237
+ attrs[:score].should be_nil
238
+ end
239
+
240
+ end
241
+
242
+ context "when associations provided in the attributes" do
243
+
244
+ context "when association is a has_one" do
245
+
246
+ before do
247
+ @name = Name.new(:first_name => "Testy")
248
+ @attributes = {
249
+ :name => @name
250
+ }
251
+ @person = Person.new(@attributes)
252
+ end
253
+
254
+ it "sets the associations" do
255
+ @person.name.should == @name
256
+ end
257
+
258
+ end
259
+
260
+ context "when association is a belongs_to" do
261
+
262
+ before do
263
+ @person = Person.new
264
+ @name = Name.new(:first_name => "Tyler", :person => @person)
265
+ end
266
+
267
+ it "sets the association" do
268
+ @name.person.should == @person
269
+ end
270
+
271
+ end
272
+
273
+ end
274
+
275
+ context "when non-associations provided in the attributes" do
276
+
277
+ before do
278
+ @employer = Employer.new
279
+ @attributes = { :employer_id => @employer.id, :title => "Sir" }
280
+ @person = Person.new(@attributes)
281
+ end
282
+
283
+ it "calls the setter for the association" do
284
+ @person.employer_id.should == "1"
285
+ end
286
+
287
+ end
288
+
289
+ context "when an empty array is provided in the attributes" do
290
+
291
+ before do
292
+ @attributes = {
293
+ :aliases => []
294
+ }
295
+ @person = Person.new(@attributes)
296
+ end
297
+
298
+ it "sets the empty array" do
299
+ @person.aliases.should == []
300
+ end
301
+
302
+ end
303
+
304
+ context "when an empty hash is provided in the attributes" do
305
+
306
+ before do
307
+ @attributes = {
308
+ :map => {}
309
+ }
310
+ @person = Person.new(@attributes)
311
+ end
312
+
313
+ it "sets the empty hash" do
314
+ @person.map.should == {}
315
+ end
316
+
317
+ end
318
+
319
+ end
320
+
321
+ context "updating when attributes already exist" do
322
+
323
+ before do
324
+ @person = Person.new(:title => "Sir")
325
+ @attributes = { :dob => "2000-01-01" }
326
+ end
327
+
328
+ it "only overwrites supplied attributes" do
329
+ @person.process(@attributes)
330
+ @person.title.should == "Sir"
331
+ end
332
+
333
+ end
334
+
335
+ describe "#read_attribute" do
336
+
337
+ context "when attribute does not exist" do
338
+
339
+ before do
340
+ @person = Person.new
341
+ end
342
+
343
+ it "returns the default value" do
344
+ @person.age.should == 100
345
+ @person.pets.should == false
346
+ end
347
+
348
+ end
349
+
350
+ context "when attribute is not accessible" do
351
+
352
+ before do
353
+ @person = Person.new
354
+ @person.owner_id = 5
355
+ end
356
+
357
+ it "returns the value" do
358
+ @person.read_attribute(:owner_id).should == 5
359
+ end
360
+ end
361
+
362
+ end
363
+
364
+ describe "#remove_attribute" do
365
+
366
+ context "when the attribute exists" do
367
+
368
+ it "removes the attribute" do
369
+ person = Person.new(:title => "Sir")
370
+ person.remove_attribute(:title)
371
+ person.title.should be_nil
372
+ end
373
+
374
+ end
375
+
376
+ context "when the attribute does not exist" do
377
+
378
+ it "does nothing" do
379
+ person = Person.new
380
+ person.remove_attribute(:title)
381
+ person.title.should be_nil
382
+ end
383
+
384
+ end
385
+
386
+ end
387
+
388
+ describe "#write_attribute" do
389
+
390
+ context "when attribute does not exist" do
391
+
392
+ before do
393
+ @person = Person.new
394
+ end
395
+
396
+ it "returns the default value" do
397
+ @person.age = nil
398
+ @person.age.should == 100
399
+ end
400
+
401
+ end
402
+
403
+ context "when field has a default value" do
404
+
405
+ before do
406
+ @person = Person.new
407
+ end
408
+
409
+ it "should allow overwriting of the default value" do
410
+ @person.terms = true
411
+ @person.terms.should be_true
412
+ end
413
+
414
+ end
415
+
416
+ end
417
+
418
+ describe "#attributes=" do
419
+ it 'should be a alias of write_attributes' do
420
+
421
+ end
422
+ end
423
+
424
+ [:attributes=, :write_attributes].each do |method|
425
+ describe "##{method}" do
426
+
427
+ context "typecasting" do
428
+
429
+ before do
430
+ @person = Person.new
431
+ @attributes = { :age => "50" }
432
+ end
433
+
434
+ it "properly casts values" do
435
+ @person.send(method, @attributes)
436
+ @person.age.should == 50
437
+ end
438
+
439
+ it "allows passing of nil" do
440
+ @person.send(method, nil)
441
+ @person.age.should == 100
442
+ end
443
+
444
+ end
445
+
446
+ context "on a parent document" do
447
+
448
+ context "when the parent has a has many through a has one" do
449
+
450
+ before do
451
+ @owner = PetOwner.new(:title => "Mr")
452
+ @pet = Pet.new(:name => "Fido")
453
+ @owner.pet = @pet
454
+ @vet_visit = VetVisit.new(:date => Date.today)
455
+ @pet.vet_visits = [@vet_visit]
456
+ end
457
+
458
+ it "does not overwrite child attributes if not in the hash" do
459
+ @owner.send(method, { :pet => { :name => "Bingo" } })
460
+ @owner.pet.name.should == "Bingo"
461
+ @owner.pet.vet_visits.size.should == 1
462
+ end
463
+
464
+ end
465
+
466
+ end
467
+
468
+ context "on a child document" do
469
+
470
+ context "when child is part of a has one" do
471
+
472
+ before do
473
+ @person = Person.new(:title => "Sir", :age => 30)
474
+ @name = Name.new(:first_name => "Test", :last_name => "User")
475
+ @person.name = @name
476
+ end
477
+
478
+ it "sets the child attributes on the parent" do
479
+ @name.send(method, :first_name => "Test2", :last_name => "User2")
480
+ @person.attributes[:name].should ==
481
+ { "_id" => "test-user", "first_name" => "Test2", "last_name" => "User2", "_type" => "Name" }
482
+ end
483
+
484
+ end
485
+
486
+ context "when child is part of a has many" do
487
+
488
+ before do
489
+ @person = Person.new(:title => "Sir")
490
+ @address = Address.new(:street => "Test")
491
+ @person.addresses << @address
492
+ end
493
+
494
+ it "updates the child attributes on the parent" do
495
+ @address.send(method, "street" => "Test2")
496
+ @person.attributes[:addresses].should ==
497
+ [ { "_id" => "test", "street" => "Test2", "_type" => "Address" } ]
498
+ end
499
+
500
+ end
501
+
502
+ end
503
+ end
504
+
505
+ end
506
+
507
+ end