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,193 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Associations::EmbeddedIn do
4
+
5
+ let(:child) do
6
+ Name.new(:first_name => "Drexel", :last_name => "Spivey")
7
+ end
8
+
9
+ let(:target) do
10
+ Person.new(:title => "Pimp")
11
+ end
12
+
13
+ let(:options) do
14
+ Mongoid::Associations::Options.new(:name => :person, :inverse_of => :name)
15
+ end
16
+
17
+ let(:has_many_options) do
18
+ Mongoid::Associations::Options.new(:name => :person, :inverse_of => :addresses)
19
+ end
20
+
21
+ describe "#find" do
22
+
23
+ before do
24
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
25
+ end
26
+
27
+ context "when finding by id" do
28
+
29
+ it "always returns the target document" do
30
+ @association.find("").should == target
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ describe "#initialize" do
38
+
39
+ before do
40
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
41
+ end
42
+
43
+ it "sets the target" do
44
+ @association.target.should == target
45
+ end
46
+
47
+ it "sets the options" do
48
+ @association.options.should == options
49
+ end
50
+
51
+ end
52
+
53
+ describe "#initialize" do
54
+
55
+ before do
56
+ @parent = Person.new(:title => "Dr")
57
+ @name = Name.new(:first_name => "Richard", :last_name => "Dawkins")
58
+ @parent.name = @name
59
+ @block = Proc.new {
60
+ def extension
61
+ "Testing"
62
+ end
63
+ }
64
+ @options = Mongoid::Associations::Options.new(:name => :person, :extend => @block)
65
+ @association = Mongoid::Associations::EmbeddedIn.new(@parent, @options)
66
+ end
67
+
68
+ context "when the options have an extension" do
69
+
70
+ it "adds the extension module" do
71
+ @association.extension.should == "Testing"
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ describe ".instantiate" do
79
+
80
+ context "when parent exists" do
81
+
82
+ before do
83
+ @parent = stub
84
+ @target = stub(:_parent => @parent)
85
+ @association = Mongoid::Associations::EmbeddedIn.instantiate(@target, options)
86
+ end
87
+
88
+ it "sets the parent to the target" do
89
+ @association.target.should == @parent
90
+ end
91
+
92
+ end
93
+
94
+ context "when parent is nil" do
95
+
96
+ before do
97
+ @document = stub(:_parent => nil)
98
+ end
99
+
100
+ it "returns nil" do
101
+ Mongoid::Associations::EmbeddedIn.instantiate(@document, options).should be_nil
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
108
+ describe ".macro" do
109
+
110
+ it "returns :embedded_in" do
111
+ Mongoid::Associations::EmbeddedIn.macro.should == :embedded_in
112
+ end
113
+
114
+ end
115
+
116
+ describe "#method_missing" do
117
+
118
+ before do
119
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
120
+ end
121
+
122
+ context "when method is a getter" do
123
+
124
+ it "delegates to the target" do
125
+ @association.title.should == "Pimp"
126
+ end
127
+
128
+ end
129
+
130
+ context "when method is a setter" do
131
+
132
+ before do
133
+ @association.title = "Dealer"
134
+ end
135
+
136
+ it "delegates to the target" do
137
+ @association.title.should == "Dealer"
138
+ end
139
+
140
+ end
141
+
142
+ context "when method does not exist" do
143
+
144
+ it "raises an error" do
145
+ lambda { @association.nothing }.should raise_error(NoMethodError)
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ describe ".update" do
153
+
154
+ context "when child is a has one" do
155
+
156
+ before do
157
+ @name = Name.new(:first_name => "Test", :last_name => "User")
158
+ @person = Person.new(:title => "Mrs")
159
+ @association = Mongoid::Associations::EmbeddedIn.update(@person, @name, options)
160
+ end
161
+
162
+ it "updates the parent document" do
163
+ @person.name.should == @name
164
+ end
165
+
166
+ it "updates the parent attributes" do
167
+ @person.attributes[:name].except(:_id).should ==
168
+ { "first_name" => "Test", "last_name" => "User", "_type" => "Name" }
169
+ end
170
+
171
+ it "returns the proxy association" do
172
+ @association.target.should == @person
173
+ end
174
+
175
+ end
176
+
177
+ context "when child is a has many" do
178
+
179
+ before do
180
+ @address = Address.new(:street => "Broadway")
181
+ @person = Person.new(:title => "Mrs")
182
+ Mongoid::Associations::EmbeddedIn.update(@person, @address, has_many_options)
183
+ end
184
+
185
+ it "updates the parent document" do
186
+ @person.addresses.first.should == @address
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,516 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Associations::EmbedsMany do
4
+
5
+ before do
6
+ @attributes = { "addresses" => [
7
+ { "_id" => "street-1", "street" => "Street 1", "state" => "CA" },
8
+ { "_id" => "street-2", "street" => "Street 2" } ] }
9
+ @document = stub(:raw_attributes => @attributes, :add_observer => true, :observe => true)
10
+ end
11
+
12
+ describe "#[]" do
13
+
14
+ before do
15
+ @association = Mongoid::Associations::EmbedsMany.new(
16
+ @document,
17
+ Mongoid::Associations::Options.new(:name => :addresses)
18
+ )
19
+ end
20
+
21
+ context "when the index is present in the association" do
22
+
23
+ it "returns the document at the index" do
24
+ @association[0].should be_a_kind_of(Address)
25
+ @association[0].street.should == "Street 1"
26
+ end
27
+
28
+ end
29
+
30
+ context "when the index is not present in the association" do
31
+
32
+ it "returns nil" do
33
+ @association[3].should be_nil
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ describe "#<<" do
41
+
42
+ before do
43
+ @association = Mongoid::Associations::EmbedsMany.new(
44
+ @document,
45
+ Mongoid::Associations::Options.new(:name => :addresses)
46
+ )
47
+ @address = Address.new
48
+ end
49
+
50
+ it "adds the parent document before appending to the array" do
51
+ @association << @address
52
+ @association.length.should == 3
53
+ @address._parent.should == @document
54
+ end
55
+
56
+ it "allows multiple additions" do
57
+ @association << @address
58
+ @association << @address
59
+ @association.length.should == 4
60
+ end
61
+
62
+ end
63
+
64
+ describe "#build" do
65
+
66
+ context "setting the parent relationship" do
67
+
68
+ before do
69
+ @person = Person.new
70
+ end
71
+
72
+ it "happens before any other operation" do
73
+ address = @person.addresses.build(:set_parent => true, :street => "Madison Ave")
74
+ address._parent.should == @person
75
+ @person.addresses.first.should == address
76
+ end
77
+
78
+ end
79
+
80
+ context "when a type is not provided" do
81
+
82
+ before do
83
+ @association = Mongoid::Associations::EmbedsMany.new(
84
+ @document,
85
+ Mongoid::Associations::Options.new(:name => :addresses)
86
+ )
87
+ end
88
+
89
+ it "adds a new document to the array with the suppied parameters" do
90
+ @association.build({ :street => "Street 1" })
91
+ @association.length.should == 3
92
+ @association[2].should be_a_kind_of(Address)
93
+ @association[2].street.should == "Street 1"
94
+ end
95
+
96
+ it "returns the newly built object in the association" do
97
+ address = @association.build({ :street => "Yet Another" })
98
+ address.should be_a_kind_of(Address)
99
+ address.street.should == "Yet Another"
100
+ end
101
+
102
+ end
103
+
104
+ context "when a type is provided" do
105
+
106
+ before do
107
+ @association = Mongoid::Associations::EmbedsMany.new(
108
+ @document,
109
+ Mongoid::Associations::Options.new(:name => :shapes)
110
+ )
111
+ end
112
+
113
+ it "instantiates a class of the type" do
114
+ circle = @association.build({ :radius => 100 }, Circle)
115
+ circle.should be_a_kind_of(Circle)
116
+ circle.radius.should == 100
117
+ end
118
+
119
+ end
120
+
121
+ end
122
+
123
+ describe "#create" do
124
+
125
+ context "when a type is not provided" do
126
+
127
+ before do
128
+ @association = Mongoid::Associations::EmbedsMany.new(
129
+ @document,
130
+ Mongoid::Associations::Options.new(:name => :addresses)
131
+ )
132
+ @address = mock(:parentize => true, :write_attributes => true)
133
+ Address.expects(:instantiate).returns(@address)
134
+ @address.expects(:run_callbacks).with(:create).yields
135
+ end
136
+
137
+ it "builds and saves a new object" do
138
+ @address.expects(:save).returns(true)
139
+ address = @association.create({ :street => "Yet Another" })
140
+ address.should == @address
141
+ end
142
+
143
+ end
144
+
145
+ context "when a type is provided" do
146
+
147
+ before do
148
+ @association = Mongoid::Associations::EmbedsMany.new(
149
+ @document,
150
+ Mongoid::Associations::Options.new(:name => :shapes)
151
+ )
152
+ @circle = mock(:parentize => true, :write_attributes => true)
153
+ Circle.expects(:instantiate).returns(@circle)
154
+ @circle.expects(:run_callbacks).with(:create).yields
155
+ end
156
+
157
+ it "instantiates a class of that type" do
158
+ @circle.expects(:save).returns(true)
159
+ circle = @association.create({ :radius => 100 }, Circle)
160
+ circle.should == @circle
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+
167
+ describe "#create!" do
168
+
169
+ context "when validations pass" do
170
+
171
+ before do
172
+ @association = Mongoid::Associations::EmbedsMany.new(
173
+ @document,
174
+ Mongoid::Associations::Options.new(:name => :addresses)
175
+ )
176
+ @address = mock(:parentize => true, :write_attributes => true, :errors => [])
177
+ Address.expects(:instantiate).returns(@address)
178
+ @address.expects(:run_callbacks).with(:create).yields
179
+ end
180
+
181
+ it "builds and saves a new object" do
182
+ @address.expects(:save).returns(true)
183
+ address = @association.create!({ :street => "Yet Another" })
184
+ address.should == @address
185
+ end
186
+ end
187
+
188
+ context "when validations fail" do
189
+
190
+ before do
191
+ @association = Mongoid::Associations::EmbedsMany.new(
192
+ @document,
193
+ Mongoid::Associations::Options.new(:name => :addresses)
194
+ )
195
+ @address = mock(:parentize => true, :write_attributes => true, :errors => [ "test" ])
196
+ Address.expects(:instantiate).returns(@address)
197
+ @address.expects(:run_callbacks).with(:create).yields
198
+ end
199
+
200
+ it "builds and saves a new object" do
201
+ @address.expects(:save).returns(false)
202
+ lambda {
203
+ @association.create!({ :street => "Yet Another" })
204
+ }.should raise_error(Mongoid::Errors::Validations)
205
+ end
206
+ end
207
+ end
208
+
209
+ describe "#concat" do
210
+
211
+ before do
212
+ @association = Mongoid::Associations::EmbedsMany.new(
213
+ @document,
214
+ Mongoid::Associations::Options.new(:name => :addresses)
215
+ )
216
+ @address = Address.new
217
+ end
218
+
219
+ it "adds the parent document before appending to the array" do
220
+ @association.concat [@address]
221
+ @association.length.should == 3
222
+ @address._parent.should == @document
223
+ end
224
+
225
+ end
226
+
227
+ describe "#clear" do
228
+
229
+ before do
230
+ @association = Mongoid::Associations::EmbedsMany.new(
231
+ @document,
232
+ Mongoid::Associations::Options.new(:name => :addresses)
233
+ )
234
+ @address = Address.new
235
+ @association << @address
236
+ end
237
+
238
+ it "clears out the association" do
239
+ @association.clear
240
+ @association.size.should == 0
241
+ end
242
+
243
+ end
244
+
245
+ describe "#find" do
246
+
247
+ before do
248
+ @association = Mongoid::Associations::EmbedsMany.new(
249
+ @document,
250
+ Mongoid::Associations::Options.new(:name => :addresses)
251
+ )
252
+ end
253
+
254
+ context "when finding all" do
255
+
256
+ it "returns all the documents" do
257
+ @association.find(:all).should == @association
258
+ end
259
+
260
+ end
261
+
262
+ context "when finding by id" do
263
+
264
+ it "returns the document in the array with that id" do
265
+ address = @association.find("street-2")
266
+ address.should_not be_nil
267
+ end
268
+
269
+ end
270
+
271
+ end
272
+
273
+ describe "#first" do
274
+
275
+ context "when there are elements in the array" do
276
+
277
+ before do
278
+ @association = Mongoid::Associations::EmbedsMany.new(
279
+ @document,
280
+ Mongoid::Associations::Options.new(:name => :addresses)
281
+ )
282
+ end
283
+
284
+ it "returns the first element" do
285
+ @association.first.should be_a_kind_of(Address)
286
+ @association.first.street.should == "Street 1"
287
+ end
288
+
289
+ end
290
+
291
+ context "when the array is empty" do
292
+
293
+ before do
294
+ @association = Mongoid::Associations::EmbedsMany.new(
295
+ Person.new,
296
+ Mongoid::Associations::Options.new(:name => :addresses)
297
+ )
298
+ end
299
+
300
+ it "returns nil" do
301
+ @association.first.should be_nil
302
+ end
303
+
304
+ end
305
+
306
+ end
307
+
308
+ describe "#initialize" do
309
+
310
+ context "when no extension exists" do
311
+
312
+ before do
313
+ @canvas = stub(:raw_attributes => { "shapes" => [{ "_type" => "Circle", "radius" => 5 }] }, :observe => true)
314
+ @association = Mongoid::Associations::EmbedsMany.new(
315
+ @canvas,
316
+ Mongoid::Associations::Options.new(:name => :shapes)
317
+ )
318
+ end
319
+
320
+ it "creates the classes based on their types" do
321
+ circle = @association.first
322
+ circle.should be_a_kind_of(Circle)
323
+ circle.radius.should == 5
324
+ end
325
+
326
+ end
327
+
328
+ context "when an extension is in the options" do
329
+
330
+ before do
331
+ @person = Person.new
332
+ @block = Proc.new do
333
+ def extension
334
+ "Testing"
335
+ end
336
+ end
337
+ @association = Mongoid::Associations::EmbedsMany.new(
338
+ @person,
339
+ Mongoid::Associations::Options.new(:name => :addresses, :extend => @block)
340
+ )
341
+ end
342
+
343
+ it "adds the extension module" do
344
+ @association.extension.should == "Testing"
345
+ end
346
+
347
+ end
348
+
349
+ end
350
+
351
+ describe ".instantiate" do
352
+
353
+ it "delegates to new" do
354
+ Mongoid::Associations::EmbedsMany.expects(:new).with(@document, @options)
355
+ Mongoid::Associations::EmbedsMany.instantiate(@document, @options)
356
+ end
357
+
358
+ end
359
+
360
+ describe "#length" do
361
+
362
+ context "#length" do
363
+
364
+ it "returns the length of the delegated array" do
365
+ @association = Mongoid::Associations::EmbedsMany.new(
366
+ @document,
367
+ Mongoid::Associations::Options.new(:name => :addresses)
368
+ )
369
+ @association.length.should == 2
370
+ end
371
+
372
+ end
373
+
374
+ end
375
+
376
+ describe ".macro" do
377
+
378
+ it "returns :embeds_many" do
379
+ Mongoid::Associations::EmbedsMany.macro.should == :embeds_many
380
+ end
381
+
382
+ end
383
+
384
+ describe "#nested_build" do
385
+
386
+ before do
387
+ @association = Mongoid::Associations::EmbedsMany.new(
388
+ @document,
389
+ Mongoid::Associations::Options.new(:name => :addresses)
390
+ )
391
+ end
392
+
393
+ it "returns the newly built object in the association" do
394
+ @association.nested_build({ "0" => { :street => "Yet Another" } })
395
+ @association.size.should == 3
396
+ @association.last.street.should == "Yet Another"
397
+ end
398
+
399
+ end
400
+
401
+ describe "#method_missing" do
402
+
403
+ context "when the association class has a criteria class method" do
404
+
405
+ before do
406
+ @association = Mongoid::Associations::EmbedsMany.new(
407
+ @document,
408
+ Mongoid::Associations::Options.new(:name => :addresses)
409
+ )
410
+ end
411
+
412
+ it "returns the criteria" do
413
+ @association.california.should be_a_kind_of(Mongoid::Criteria)
414
+ end
415
+
416
+ it "sets the documents on the criteria" do
417
+ criteria = @association.california
418
+ criteria.documents.should == @association.entries
419
+ end
420
+
421
+ it "returns the scoped documents" do
422
+ addresses = @association.california
423
+ addresses.size.should == 1
424
+ addresses.first.should be_a_kind_of(Address)
425
+ addresses.first.state.should == "CA"
426
+ end
427
+
428
+ end
429
+
430
+ context "when no class method exists" do
431
+
432
+ before do
433
+ @association = Mongoid::Associations::EmbedsMany.new(
434
+ @document,
435
+ Mongoid::Associations::Options.new(:name => :addresses)
436
+ )
437
+ end
438
+
439
+ it "delegates to the array" do
440
+ @association.entries.size.should == 2
441
+ end
442
+
443
+ end
444
+
445
+ end
446
+
447
+ describe "#paginate" do
448
+
449
+ before do
450
+ @association = Mongoid::Associations::EmbedsMany.new(
451
+ @document,
452
+ Mongoid::Associations::Options.new(:name => :addresses)
453
+ )
454
+ @options = { :page => 1, :per_page => 10 }
455
+ @criteria = mock
456
+ end
457
+
458
+ it "creates a criteria and paginates it" do
459
+ Mongoid::Criteria.expects(:translate).with(Address, @options).returns(@criteria)
460
+ @criteria.expects(:documents=).with(@association.target)
461
+ @criteria.expects(:paginate).returns([])
462
+ @association.paginate(@options).should == []
463
+ end
464
+ end
465
+
466
+ describe "#push" do
467
+
468
+ before do
469
+ @association = Mongoid::Associations::EmbedsMany.new(
470
+ @document,
471
+ Mongoid::Associations::Options.new(:name => :addresses)
472
+ )
473
+ @address = Address.new
474
+ end
475
+
476
+ it "adds the parent document before appending to the array" do
477
+ @association.push @address
478
+ @association.length.should == 3
479
+ @address._parent.should == @document
480
+ end
481
+
482
+ it "appends the document to the end of the array" do
483
+ @association.push(Address.new)
484
+ @association.length.should == 3
485
+ end
486
+
487
+ end
488
+
489
+ describe ".update" do
490
+
491
+ before do
492
+ @address = Address.new(:street => "Madison Ave")
493
+ @person = Person.new(:title => "Sir")
494
+ @association = Mongoid::Associations::EmbedsMany.update(
495
+ [@address],
496
+ @person,
497
+ Mongoid::Associations::Options.new(:name => :addresses)
498
+ )
499
+ end
500
+
501
+ it "parentizes the child document" do
502
+ @address._parent.should == @person
503
+ end
504
+
505
+ it "sets the attributes of the child on the parent" do
506
+ @person.attributes[:addresses].should ==
507
+ [{ "_id" => "madison-ave", "street" => "Madison Ave", "_type" => "Address" }]
508
+ end
509
+
510
+ it "returns the association proxy" do
511
+ @association.target.size.should == 1
512
+ end
513
+
514
+ end
515
+
516
+ end