mongoid-pre 2.0.0.beta1

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 (246) hide show
  1. data/.gitignore +6 -0
  2. data/.watchr +24 -0
  3. data/MIT_LICENSE +20 -0
  4. data/README.rdoc +49 -0
  5. data/Rakefile +52 -0
  6. data/VERSION +1 -0
  7. data/caliper.yml +4 -0
  8. data/lib/mongoid.rb +135 -0
  9. data/lib/mongoid/associations.rb +263 -0
  10. data/lib/mongoid/associations/belongs_to_related.rb +59 -0
  11. data/lib/mongoid/associations/embedded_in.rb +64 -0
  12. data/lib/mongoid/associations/embeds_many.rb +193 -0
  13. data/lib/mongoid/associations/embeds_one.rb +95 -0
  14. data/lib/mongoid/associations/has_many_related.rb +133 -0
  15. data/lib/mongoid/associations/has_one_related.rb +81 -0
  16. data/lib/mongoid/associations/meta_data.rb +28 -0
  17. data/lib/mongoid/associations/options.rb +52 -0
  18. data/lib/mongoid/associations/proxy.rb +31 -0
  19. data/lib/mongoid/attributes.rb +185 -0
  20. data/lib/mongoid/callbacks.rb +18 -0
  21. data/lib/mongoid/collection.rb +119 -0
  22. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  23. data/lib/mongoid/collections/master.rb +28 -0
  24. data/lib/mongoid/collections/mimic.rb +46 -0
  25. data/lib/mongoid/collections/operations.rb +41 -0
  26. data/lib/mongoid/collections/slaves.rb +44 -0
  27. data/lib/mongoid/commands.rb +161 -0
  28. data/lib/mongoid/commands/create.rb +19 -0
  29. data/lib/mongoid/commands/delete.rb +16 -0
  30. data/lib/mongoid/commands/delete_all.rb +25 -0
  31. data/lib/mongoid/commands/deletion.rb +18 -0
  32. data/lib/mongoid/commands/destroy.rb +17 -0
  33. data/lib/mongoid/commands/destroy_all.rb +25 -0
  34. data/lib/mongoid/commands/save.rb +30 -0
  35. data/lib/mongoid/components.rb +31 -0
  36. data/lib/mongoid/config.rb +86 -0
  37. data/lib/mongoid/contexts.rb +25 -0
  38. data/lib/mongoid/contexts/enumerable.rb +151 -0
  39. data/lib/mongoid/contexts/ids.rb +25 -0
  40. data/lib/mongoid/contexts/mongo.rb +285 -0
  41. data/lib/mongoid/contexts/paging.rb +42 -0
  42. data/lib/mongoid/criteria.rb +239 -0
  43. data/lib/mongoid/criterion/complex.rb +21 -0
  44. data/lib/mongoid/criterion/exclusion.rb +65 -0
  45. data/lib/mongoid/criterion/inclusion.rb +93 -0
  46. data/lib/mongoid/criterion/optional.rb +136 -0
  47. data/lib/mongoid/cursor.rb +82 -0
  48. data/lib/mongoid/deprecation.rb +22 -0
  49. data/lib/mongoid/dirty.rb +203 -0
  50. data/lib/mongoid/document.rb +306 -0
  51. data/lib/mongoid/errors.rb +77 -0
  52. data/lib/mongoid/extensions.rb +99 -0
  53. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  54. data/lib/mongoid/extensions/array/aliasing.rb +4 -0
  55. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  56. data/lib/mongoid/extensions/array/conversions.rb +27 -0
  57. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  58. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  59. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  60. data/lib/mongoid/extensions/boolean/conversions.rb +16 -0
  61. data/lib/mongoid/extensions/date/conversions.rb +15 -0
  62. data/lib/mongoid/extensions/datetime/conversions.rb +17 -0
  63. data/lib/mongoid/extensions/float/conversions.rb +16 -0
  64. data/lib/mongoid/extensions/hash/accessors.rb +38 -0
  65. data/lib/mongoid/extensions/hash/assimilation.rb +30 -0
  66. data/lib/mongoid/extensions/hash/conversions.rb +15 -0
  67. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  68. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  69. data/lib/mongoid/extensions/integer/conversions.rb +16 -0
  70. data/lib/mongoid/extensions/nil/assimilation.rb +13 -0
  71. data/lib/mongoid/extensions/object/conversions.rb +27 -0
  72. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  73. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  74. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  75. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  76. data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
  77. data/lib/mongoid/extensions/time/conversions.rb +18 -0
  78. data/lib/mongoid/extras.rb +61 -0
  79. data/lib/mongoid/factory.rb +19 -0
  80. data/lib/mongoid/field.rb +52 -0
  81. data/lib/mongoid/fields.rb +62 -0
  82. data/lib/mongoid/finders.rb +136 -0
  83. data/lib/mongoid/identity.rb +39 -0
  84. data/lib/mongoid/indexes.rb +27 -0
  85. data/lib/mongoid/javascript.rb +21 -0
  86. data/lib/mongoid/javascript/functions.yml +37 -0
  87. data/lib/mongoid/matchers.rb +36 -0
  88. data/lib/mongoid/matchers/all.rb +11 -0
  89. data/lib/mongoid/matchers/default.rb +26 -0
  90. data/lib/mongoid/matchers/exists.rb +13 -0
  91. data/lib/mongoid/matchers/gt.rb +11 -0
  92. data/lib/mongoid/matchers/gte.rb +11 -0
  93. data/lib/mongoid/matchers/in.rb +11 -0
  94. data/lib/mongoid/matchers/lt.rb +11 -0
  95. data/lib/mongoid/matchers/lte.rb +11 -0
  96. data/lib/mongoid/matchers/ne.rb +11 -0
  97. data/lib/mongoid/matchers/nin.rb +11 -0
  98. data/lib/mongoid/matchers/size.rb +11 -0
  99. data/lib/mongoid/memoization.rb +27 -0
  100. data/lib/mongoid/named_scope.rb +42 -0
  101. data/lib/mongoid/observable.rb +30 -0
  102. data/lib/mongoid/paths.rb +54 -0
  103. data/lib/mongoid/persistence.rb +27 -0
  104. data/lib/mongoid/persistence/command.rb +20 -0
  105. data/lib/mongoid/persistence/insert.rb +71 -0
  106. data/lib/mongoid/persistence/update.rb +78 -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 +4 -0
  113. data/lib/mongoid/validations/uniqueness.rb +22 -0
  114. data/lib/mongoid/versioning.rb +26 -0
  115. data/mongoid.gemspec +413 -0
  116. data/perf/benchmark.rb +77 -0
  117. data/spec/integration/mongoid/associations_spec.rb +340 -0
  118. data/spec/integration/mongoid/attributes_spec.rb +22 -0
  119. data/spec/integration/mongoid/commands_spec.rb +230 -0
  120. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  121. data/spec/integration/mongoid/criteria_spec.rb +272 -0
  122. data/spec/integration/mongoid/dirty_spec.rb +70 -0
  123. data/spec/integration/mongoid/document_spec.rb +650 -0
  124. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  125. data/spec/integration/mongoid/finders_spec.rb +119 -0
  126. data/spec/integration/mongoid/inheritance_spec.rb +137 -0
  127. data/spec/integration/mongoid/named_scope_spec.rb +46 -0
  128. data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
  129. data/spec/models/address.rb +39 -0
  130. data/spec/models/animal.rb +6 -0
  131. data/spec/models/callbacks.rb +18 -0
  132. data/spec/models/comment.rb +8 -0
  133. data/spec/models/country_code.rb +6 -0
  134. data/spec/models/employer.rb +5 -0
  135. data/spec/models/game.rb +7 -0
  136. data/spec/models/inheritance.rb +56 -0
  137. data/spec/models/location.rb +5 -0
  138. data/spec/models/mixed_drink.rb +4 -0
  139. data/spec/models/name.rb +13 -0
  140. data/spec/models/namespacing.rb +11 -0
  141. data/spec/models/patient.rb +6 -0
  142. data/spec/models/person.rb +99 -0
  143. data/spec/models/pet.rb +7 -0
  144. data/spec/models/pet_owner.rb +6 -0
  145. data/spec/models/phone.rb +7 -0
  146. data/spec/models/post.rb +15 -0
  147. data/spec/models/translation.rb +5 -0
  148. data/spec/models/vet_visit.rb +5 -0
  149. data/spec/spec.opts +3 -0
  150. data/spec/spec_helper.rb +31 -0
  151. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +145 -0
  152. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  153. data/spec/unit/mongoid/associations/embeds_many_spec.rb +516 -0
  154. data/spec/unit/mongoid/associations/embeds_one_spec.rb +282 -0
  155. data/spec/unit/mongoid/associations/has_many_related_spec.rb +418 -0
  156. data/spec/unit/mongoid/associations/has_one_related_spec.rb +179 -0
  157. data/spec/unit/mongoid/associations/meta_data_spec.rb +88 -0
  158. data/spec/unit/mongoid/associations/options_spec.rb +192 -0
  159. data/spec/unit/mongoid/associations_spec.rb +595 -0
  160. data/spec/unit/mongoid/attributes_spec.rb +507 -0
  161. data/spec/unit/mongoid/callbacks_spec.rb +55 -0
  162. data/spec/unit/mongoid/collection_spec.rb +187 -0
  163. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  164. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  165. data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
  166. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  167. data/spec/unit/mongoid/commands/create_spec.rb +31 -0
  168. data/spec/unit/mongoid/commands/delete_all_spec.rb +59 -0
  169. data/spec/unit/mongoid/commands/delete_spec.rb +38 -0
  170. data/spec/unit/mongoid/commands/destroy_all_spec.rb +21 -0
  171. data/spec/unit/mongoid/commands/destroy_spec.rb +51 -0
  172. data/spec/unit/mongoid/commands/save_spec.rb +107 -0
  173. data/spec/unit/mongoid/commands_spec.rb +270 -0
  174. data/spec/unit/mongoid/config_spec.rb +176 -0
  175. data/spec/unit/mongoid/contexts/enumerable_spec.rb +421 -0
  176. data/spec/unit/mongoid/contexts/mongo_spec.rb +682 -0
  177. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  178. data/spec/unit/mongoid/criteria_spec.rb +824 -0
  179. data/spec/unit/mongoid/criterion/complex_spec.rb +19 -0
  180. data/spec/unit/mongoid/criterion/exclusion_spec.rb +91 -0
  181. data/spec/unit/mongoid/criterion/inclusion_spec.rb +219 -0
  182. data/spec/unit/mongoid/criterion/optional_spec.rb +319 -0
  183. data/spec/unit/mongoid/cursor_spec.rb +74 -0
  184. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  185. data/spec/unit/mongoid/dirty_spec.rb +286 -0
  186. data/spec/unit/mongoid/document_spec.rb +818 -0
  187. data/spec/unit/mongoid/errors_spec.rb +103 -0
  188. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  189. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  190. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +35 -0
  191. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  192. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +22 -0
  193. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  194. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  195. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +102 -0
  196. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +67 -0
  197. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  198. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  199. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +46 -0
  200. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +21 -0
  201. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  202. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  203. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  204. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +24 -0
  205. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +57 -0
  206. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  207. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +17 -0
  208. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  209. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +91 -0
  210. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +70 -0
  211. data/spec/unit/mongoid/extras_spec.rb +102 -0
  212. data/spec/unit/mongoid/factory_spec.rb +31 -0
  213. data/spec/unit/mongoid/field_spec.rb +143 -0
  214. data/spec/unit/mongoid/fields_spec.rb +181 -0
  215. data/spec/unit/mongoid/finders_spec.rb +404 -0
  216. data/spec/unit/mongoid/identity_spec.rb +109 -0
  217. data/spec/unit/mongoid/indexes_spec.rb +93 -0
  218. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  219. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  220. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  221. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  222. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  223. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  224. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  225. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  226. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  227. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  228. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  229. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  230. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  231. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  232. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  233. data/spec/unit/mongoid/observable_spec.rb +46 -0
  234. data/spec/unit/mongoid/paths_spec.rb +124 -0
  235. data/spec/unit/mongoid/persistence/insert_spec.rb +175 -0
  236. data/spec/unit/mongoid/persistence/update_spec.rb +148 -0
  237. data/spec/unit/mongoid/persistence_spec.rb +40 -0
  238. data/spec/unit/mongoid/scope_spec.rb +240 -0
  239. data/spec/unit/mongoid/state_spec.rb +83 -0
  240. data/spec/unit/mongoid/timestamps_spec.rb +25 -0
  241. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  242. data/spec/unit/mongoid/validations/uniqueness_spec.rb +47 -0
  243. data/spec/unit/mongoid/validations_spec.rb +190 -0
  244. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  245. data/spec/unit/mongoid_spec.rb +46 -0
  246. metadata +476 -0
@@ -0,0 +1,595 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Associations do
4
+
5
+ before do
6
+ @collection = stub(:name => "people")
7
+ @database = stub(:collection => @collection)
8
+ Mongoid.stubs(:database).returns(@database)
9
+ end
10
+
11
+ after do
12
+ Person.instance_variable_set(:@collection, nil)
13
+ @database = nil
14
+ @collection = nil
15
+ end
16
+
17
+ describe "#association=" do
18
+
19
+ context "when child is a has one" do
20
+
21
+ before do
22
+ @person = Person.new(:title => "Sir", :age => 30)
23
+ @name = Name.new(:first_name => "Test", :last_name => "User")
24
+ @person.name = @name
25
+ end
26
+
27
+ it "parentizes the association" do
28
+ @name._parent.should == @person
29
+ end
30
+
31
+ it "sets the child attributes on the parent" do
32
+ @person.attributes[:name].should ==
33
+ { "_id" => "test-user", "first_name" => "Test", "last_name" => "User", "_type" => "Name" }
34
+ end
35
+
36
+ end
37
+
38
+ context "when child and parent are namespaced" do
39
+
40
+ before do
41
+ @patient = Medical::Patient.new(:name => "Ridley")
42
+ @prescription = Medical::Prescription.new(:name => "Zoloft")
43
+ @patient.prescriptions << @prescription
44
+ @second = @patient.prescriptions.build(:name => "Codeine")
45
+ end
46
+
47
+ it "sets the correct association classes" do
48
+ @patient.prescriptions.first.should == @prescription
49
+ @patient.prescriptions.last.should == @second
50
+ end
51
+
52
+ end
53
+
54
+ context "when setting a parent" do
55
+
56
+ context "when the child is one level deep" do
57
+
58
+ before do
59
+ @person = Person.new(:title => "Mr")
60
+ @address = Address.new(:street => "Picadilly Circus")
61
+ @address.addressable = @person
62
+ end
63
+
64
+ it "re-parentizes the association" do
65
+ @address._parent.should == @person
66
+ end
67
+
68
+ it "adds the child attributes to the parent" do
69
+ @person.attributes[:addresses].should ==
70
+ [{ "_id" => "picadilly-circus", "street" => "Picadilly Circus", "_type" => "Address" }]
71
+ end
72
+
73
+ end
74
+
75
+ context "when the child is multiple levels deep" do
76
+
77
+ before do
78
+ @person = Person.new(:title => "Mr")
79
+ @phone = Phone.new(:number => "415-555-1212")
80
+ @person.phone_numbers = [@phone]
81
+ @country_code = CountryCode.new(:code => 1)
82
+ @phone.country_code = @country_code
83
+ end
84
+
85
+ it "properly decorates all parent references" do
86
+ @country_code.phone_number.should == @phone
87
+ @phone.person.should == @person
88
+ @country_code.phone_number.person.should == @person
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ describe "#associations" do
98
+
99
+ before do
100
+ @person = Person.new
101
+ end
102
+
103
+ it "is a hash with name keys and meta data values" do
104
+ @person.associations["addresses"].should be_a_kind_of(Mongoid::Associations::MetaData)
105
+ end
106
+ end
107
+
108
+ describe ".embedded_in" do
109
+
110
+ it "creates a reader for the association" do
111
+ address = Address.new
112
+ address.should respond_to(:addressable)
113
+ end
114
+
115
+ it "creates a writer for the association" do
116
+ address = Address.new
117
+ address.should respond_to(:addressable=)
118
+ end
119
+
120
+ it "allows the parent to be any type of class" do
121
+ phone_number = Phone.new(:number => "415-555-1212")
122
+ code = CountryCode.new(:code => 1)
123
+ phone_number.country_code = code
124
+ code.phone_number.should == phone_number
125
+ end
126
+
127
+ context "when adding an anonymous extension" do
128
+
129
+ before do
130
+ @person = Person.new(:title => "Dr")
131
+ @address = Address.new(:street => "Clarkenwell Road")
132
+ @person.addresses << @address
133
+ end
134
+
135
+ it "defines the method on the association" do
136
+ @address.addressable.extension.should == "Testing"
137
+ end
138
+
139
+ end
140
+
141
+ context "when inverse_of not supplied" do
142
+
143
+ it "raises an error" do
144
+ lambda { Person.class_eval { embedded_in :nothing } }.should raise_error
145
+ end
146
+
147
+ end
148
+
149
+ context "when navigating the graph" do
150
+
151
+ before do
152
+ @person = Person.new(:title => "Mr")
153
+ @name = Name.new(:first_name => "Mason")
154
+ @address = Address.new(:street => "King St.")
155
+ @person.name = @name
156
+ @person.addresses << @address
157
+ end
158
+
159
+ it "allows referencing another child through the parent" do
160
+ @name.person.addresses.first.should == @address
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+ describe "#build_*" do
168
+
169
+ before do
170
+ @canvas = Canvas.new
171
+ end
172
+
173
+ context "when type is passed in" do
174
+
175
+ before do
176
+ @writer = @canvas.build_writer(:speed => 250, :_type => "HtmlWriter")
177
+ end
178
+
179
+ it "returns a new document" do
180
+ @writer.should_not be_nil
181
+ end
182
+
183
+ it "returns the properly typed document" do
184
+ @writer.should be_a_kind_of(HtmlWriter)
185
+ end
186
+
187
+ it "sets the appropriate attributes" do
188
+ @writer.speed.should == 250
189
+ end
190
+
191
+ end
192
+
193
+ context "when type is not passed in" do
194
+
195
+ before do
196
+ @writer = @canvas.build_writer(:speed => 250)
197
+ end
198
+
199
+ it "returns a new document" do
200
+ @writer.should_not be_nil
201
+ end
202
+
203
+ it "returns the properly typed document" do
204
+ @writer.should be_a_kind_of(Writer)
205
+ end
206
+
207
+ it "sets the appropriate attributes" do
208
+ @writer.speed.should == 250
209
+ end
210
+
211
+ end
212
+
213
+ context "when attributes are nil" do
214
+
215
+ before do
216
+ @writer = @canvas.build_writer(nil)
217
+ end
218
+
219
+ it "defaults them to empty" do
220
+ @writer.should be_a_kind_of(Writer)
221
+ end
222
+
223
+ end
224
+
225
+ end
226
+
227
+ describe "#create_*" do
228
+
229
+ before do
230
+ @canvas = Canvas.new
231
+ end
232
+
233
+ context "when type is passed in" do
234
+
235
+ before do
236
+ Mongoid::Commands::Save.expects(:execute)
237
+ @writer = @canvas.create_writer(:speed => 250, :_type => "HtmlWriter")
238
+ end
239
+
240
+ it "returns a new document" do
241
+ @writer.should_not be_nil
242
+ end
243
+
244
+ it "returns the properly typed document" do
245
+ @writer.should be_a_kind_of(HtmlWriter)
246
+ end
247
+
248
+ it "sets the appropriate attributes" do
249
+ @writer.speed.should == 250
250
+ end
251
+
252
+ end
253
+
254
+ context "when type is not passed in" do
255
+
256
+ before do
257
+ Mongoid::Commands::Save.expects(:execute)
258
+ @writer = @canvas.create_writer(:speed => 250, :_type => "HtmlWriter")
259
+ end
260
+
261
+ it "returns a new document" do
262
+ @writer.should_not be_nil
263
+ end
264
+
265
+ it "returns the properly typed document" do
266
+ @writer.should be_a_kind_of(Writer)
267
+ end
268
+
269
+ it "sets the appropriate attributes" do
270
+ @writer.speed.should == 250
271
+ end
272
+
273
+ end
274
+
275
+ end
276
+
277
+ describe ".embeds_many" do
278
+
279
+ it "adds a new Association to the collection" do
280
+ person = Person.new
281
+ person.addresses.should_not be_nil
282
+ end
283
+
284
+ it "creates a reader for the association" do
285
+ person = Person.new
286
+ person.should respond_to(:addresses)
287
+ end
288
+
289
+ it "creates a writer for the association" do
290
+ person = Person.new
291
+ person.should respond_to(:addresses=)
292
+ end
293
+
294
+ context "when adding an anonymous extension" do
295
+
296
+ it "defines the method on the association" do
297
+ person = Person.new
298
+ person.addresses.extension.should == "Testing"
299
+ end
300
+
301
+ end
302
+
303
+ context "when setting the association directly" do
304
+
305
+ before do
306
+ @attributes = { :title => "Sir",
307
+ :addresses => [
308
+ { :street => "Street 1" },
309
+ { :street => "Street 2" } ] }
310
+ @person = Person.new(@attributes)
311
+ end
312
+
313
+ it "sets the attributes for the association" do
314
+ address = Address.new(:street => "New Street")
315
+ @person.addresses = [address]
316
+ @person.addresses.first.street.should == "New Street"
317
+ end
318
+
319
+ end
320
+
321
+ context "when a class_name is supplied" do
322
+
323
+ before do
324
+ @attributes = { :title => "Sir",
325
+ :phone_numbers => [ { :number => "404-555-1212" } ]
326
+ }
327
+ @person = Person.new(@attributes)
328
+ end
329
+
330
+ it "sets the association name" do
331
+ @person.phone_numbers.first.should == Phone.new(:number => "404-555-1212")
332
+ end
333
+
334
+ end
335
+
336
+ context "when updating objects internally" do
337
+
338
+ before do
339
+ @address = Address.new(:street => "Bourke Street")
340
+ @person = Person.new(:title => "Sir")
341
+ @person.addresses << @address
342
+ @person.update_addresses
343
+ end
344
+
345
+ it "retains its references to the original objects" do
346
+ @address.street.should == "Updated Address"
347
+ end
348
+
349
+ end
350
+
351
+ end
352
+
353
+ describe ".embeds_one" do
354
+
355
+ before do
356
+ @person = Person.new
357
+ end
358
+
359
+ it "adds a new Association to the document" do
360
+ @person.name.should be_nil
361
+ end
362
+
363
+ it "creates a reader for the association" do
364
+ @person.should respond_to(:name)
365
+ end
366
+
367
+ it "creates a writer for the association" do
368
+ @person.should respond_to(:name=)
369
+ end
370
+
371
+ it "creates a builder for the association" do
372
+ @person.should respond_to(:build_name)
373
+ end
374
+
375
+ it "creates a creator for the association" do
376
+ @person.should respond_to(:create_name)
377
+ end
378
+
379
+ context "when adding an anonymous extension" do
380
+
381
+ it "defines the method on the association" do
382
+ @person.name = Name.new(:first_name => "Richard")
383
+ @person.name.extension.should == "Testing"
384
+ end
385
+
386
+ end
387
+
388
+ context "when setting the association directly" do
389
+
390
+ before do
391
+ @attributes = { :title => "Sir",
392
+ :name => { :first_name => "Test" } }
393
+ @person = Person.new(@attributes)
394
+ end
395
+
396
+ it "sets the attributes for the association" do
397
+ name = Name.new(:first_name => "New Name")
398
+ @person.name = name
399
+ @person.name.first_name.should == "New Name"
400
+ end
401
+
402
+ end
403
+
404
+ context "when a class_name is supplied" do
405
+
406
+ before do
407
+ @attributes = { :title => "Sir",
408
+ :pet => { :name => "Fido" }
409
+ }
410
+ @person = Person.new(@attributes)
411
+ end
412
+
413
+ it "sets the association name" do
414
+ @person.pet.should == Animal.new(:name => "Fido")
415
+ end
416
+
417
+ end
418
+
419
+ end
420
+
421
+ describe ".reflect_on_association" do
422
+
423
+ it "returns the association class for the name" do
424
+ Person.reflect_on_association(:addresses).should == :embeds_many
425
+ end
426
+
427
+ end
428
+
429
+ describe ".belongs_to_related" do
430
+
431
+ before do
432
+ @game = Game.new
433
+ end
434
+
435
+ it "creates an id field for the relationship" do
436
+ @game.should respond_to(:person_id)
437
+ end
438
+
439
+ it "creates a getter for the parent" do
440
+ @game.should respond_to(:person)
441
+ end
442
+
443
+ it "defaults the foreign_key option to the name_id" do
444
+ @game.associations["person"].foreign_key.should == "person_id"
445
+ end
446
+
447
+ context "when document is root level" do
448
+
449
+ it "puts an index on the foreign key" do
450
+ Game.expects(:index).with("person_id")
451
+ Game.belongs_to_related :person
452
+ end
453
+
454
+ end
455
+
456
+ context "when using object ids" do
457
+
458
+ before do
459
+ Mongoid.use_object_ids = true
460
+ end
461
+
462
+ after do
463
+ Mongoid.use_object_ids = false
464
+ end
465
+
466
+ it "sets the foreign key as an object id" do
467
+ Game.expects(:field).with("person_id", :type => Mongo::ObjectID)
468
+ Game.belongs_to_related :person
469
+ end
470
+ end
471
+
472
+ end
473
+
474
+ describe ".has_one_related" do
475
+
476
+ before do
477
+ @person = Person.new
478
+ @game = Game.new
479
+ @person.game = @game
480
+ end
481
+
482
+ it "creates a getter for the relationship" do
483
+ @person.should respond_to(:game)
484
+ end
485
+
486
+ it "creates a setter for the relationship" do
487
+ @person.should respond_to(:game=)
488
+ end
489
+
490
+ context "when adding an anonymous extension" do
491
+
492
+ it "defines the method on the association" do
493
+ @person.game.extension.should == "Testing"
494
+ end
495
+
496
+ end
497
+
498
+ end
499
+
500
+ describe ".has_many_related" do
501
+
502
+ it "creates a getter for the association" do
503
+ Person.new.should respond_to(:posts)
504
+ end
505
+
506
+ it "creates a setter for the association" do
507
+ Person.new.should respond_to(:posts=)
508
+ end
509
+
510
+ context "when adding an anonymous extension" do
511
+
512
+ before do
513
+ @person = Person.new
514
+ end
515
+
516
+ it "defines the method on the association" do
517
+ @person.posts.extension.should == "Testing"
518
+ end
519
+
520
+ end
521
+
522
+ end
523
+
524
+ describe "#update_associations" do
525
+
526
+ context "when associations exist" do
527
+
528
+ context "when the document is a new record" do
529
+
530
+ before do
531
+ @related = stub(:id => "100", :person= => true)
532
+ @person = Person.new
533
+ @person.posts = [@related]
534
+ end
535
+
536
+ it "saves each association" do
537
+ @related.expects(:save).returns(@related)
538
+ @person.update_associations(:posts)
539
+ end
540
+
541
+ end
542
+
543
+ context "when the document is not new" do
544
+
545
+ before do
546
+ @related = stub(:id => "100", :person= => true)
547
+ @person = Person.new
548
+ @person.instance_variable_set(:@new_record, false)
549
+ @person.posts = [@related]
550
+ end
551
+
552
+ it "does not save each association" do
553
+ @person.update_associations(:posts)
554
+ end
555
+
556
+ end
557
+
558
+ end
559
+
560
+ context "when no associations exist" do
561
+
562
+ before do
563
+ @person = Person.new
564
+ end
565
+
566
+ it "does nothing" do
567
+ Post.expects(:find).returns([])
568
+ @person.update_associations(:posts)
569
+ @person.posts.first.should be_nil
570
+ end
571
+
572
+ end
573
+
574
+ end
575
+
576
+ describe "#update_association" do
577
+
578
+ context "when the association exists" do
579
+
580
+ before do
581
+ @related = stub(:id => "100", :person= => true)
582
+ @person = Person.new
583
+ @person.game = @related
584
+ end
585
+
586
+ it "saves each association" do
587
+ @related.expects(:save).returns(@related)
588
+ @person.update_association(:game)
589
+ end
590
+
591
+ end
592
+
593
+ end
594
+
595
+ end