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,703 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Contexts::Mongo do
4
+
5
+ describe "#aggregate" do
6
+
7
+ before do
8
+ @criteria = Mongoid::Criteria.new(Person)
9
+ @criteria.only(:field1)
10
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
11
+ end
12
+
13
+ context "when klass not provided" do
14
+
15
+ before do
16
+ @reduce = "function(obj, prev) { prev.count++; }"
17
+ @collection = mock
18
+ Person.expects(:collection).returns(@collection)
19
+ end
20
+
21
+ it "calls group on the collection with the aggregate js" do
22
+ @collection.expects(:group).with(
23
+ [:field1],
24
+ {:_type => {'$in' => ['Doctor', 'Person']}},
25
+ {:count => 0},
26
+ @reduce,
27
+ true
28
+ )
29
+ @context.aggregate
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#avg" do
35
+
36
+ before do
37
+ @reduce = Mongoid::Javascript.sum.gsub("[field]", "age")
38
+ @collection = mock
39
+ Person.expects(:collection).twice.returns(@collection)
40
+ @criteria = Mongoid::Criteria.new(Person)
41
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
42
+ end
43
+
44
+ it "calls group on the collection with the aggregate js" do
45
+ @collection.expects(:group).with(
46
+ nil,
47
+ {:_type => {'$in' => ['Doctor', 'Person']}},
48
+ {:sum => "start"},
49
+ @reduce
50
+ ).returns([{"sum" => 100.0}])
51
+ @cursor = mock(:count => 10)
52
+ @collection.expects(:find).returns(@cursor)
53
+ @context.avg(:age).should == 10
54
+ end
55
+ end
56
+
57
+ describe "blank?" do
58
+
59
+ before do
60
+ @criteria = Mongoid::Criteria.new(Game)
61
+ @criteria.where(:test => 'Testing')
62
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
63
+ end
64
+
65
+ context "when a document exists" do
66
+
67
+ before do
68
+ @doc = mock
69
+ @collection = mock
70
+ Game.expects(:collection).returns(@collection)
71
+ @collection.expects(:find_one).with({ :test => "Testing" }, { :fields => [ :_id ] }).returns(@doc)
72
+ end
73
+
74
+ it "returns false" do
75
+ @context.blank?.should be_false
76
+ end
77
+ end
78
+
79
+ context "when a document does not exist" do
80
+
81
+ before do
82
+ @doc = mock
83
+ @collection = mock
84
+ Game.expects(:collection).returns(@collection)
85
+ @collection.expects(:find_one).with({ :test => "Testing" }, { :fields => [ :_id ] }).returns(nil)
86
+ end
87
+
88
+ it "returns true" do
89
+ @context.blank?.should be_true
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "#count" do
95
+
96
+ before do
97
+ @criteria = Mongoid::Criteria.new(Person)
98
+ @criteria.where(:test => 'Testing')
99
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
100
+ end
101
+
102
+ context "when criteria has not been executed" do
103
+
104
+ before do
105
+ @context.instance_variable_set(:@count, 34)
106
+ end
107
+
108
+ it "returns a count from the cursor" do
109
+ @context.count.should == 34
110
+ end
111
+
112
+ end
113
+
114
+ context "when criteria has been executed" do
115
+
116
+ before do
117
+ @collection = mock
118
+ @cursor = mock
119
+ Person.expects(:collection).returns(@collection)
120
+ end
121
+
122
+ it "returns the count from the cursor without creating the documents" do
123
+ @collection.expects(:find).with(@criteria.selector, {}).returns(@cursor)
124
+ @cursor.expects(:count).returns(10)
125
+ @context.count.should == 10
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ describe "#distinct" do
133
+
134
+ before do
135
+ @criteria = Mongoid::Criteria.new(Person)
136
+ @criteria.where(:test => 'Testing')
137
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
138
+ @collection = mock
139
+ Person.expects(:collection).returns(@collection)
140
+ end
141
+
142
+ it "returns delegates to distinct on the collection" do
143
+ @collection.expects(:distinct).with(:title, @criteria.selector).returns(["Sir"])
144
+ @context.distinct(:title).should == ["Sir"]
145
+ end
146
+ end
147
+
148
+ describe "#execute" do
149
+
150
+ let(:selector) { { :field => "value" } }
151
+ let(:options) { { :skip => 20 } }
152
+
153
+ before do
154
+ @cursor = stub(:count => 500)
155
+ @collection = mock
156
+ @klass = stub(
157
+ :collection => @collection,
158
+ :hereditary => false,
159
+ :instantiate => @person,
160
+ :enslaved? => false,
161
+ :cached? => false
162
+ )
163
+ @criteria = Mongoid::Criteria.new(@klass)
164
+ @criteria.where(selector).skip(20)
165
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
166
+ end
167
+
168
+ it "calls find on the collection" do
169
+ @collection.expects(:find).with(selector, options).returns(@cursor)
170
+ @context.execute.should == @cursor
171
+ end
172
+
173
+ context "when paginating" do
174
+
175
+ it "should find the count from the cursor" do
176
+ @collection.expects(:find).with(selector, options).returns(@cursor)
177
+ @context.execute(true).should == @cursor
178
+ @context.count.should == 500
179
+ end
180
+
181
+ end
182
+
183
+ context "when field options are supplied" do
184
+
185
+ context "when _type not in the field list" do
186
+
187
+ before do
188
+ @criteria.only(:title)
189
+ @expected_options = { :skip => 20, :fields => [ :title, :_type ] }
190
+ end
191
+
192
+ it "adds _type to the fields" do
193
+ @collection.expects(:find).with(selector, @expected_options).returns(@cursor)
194
+ @context.execute.should == @cursor
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
201
+ end
202
+
203
+ describe "#group" do
204
+
205
+ before do
206
+ @criteria = Mongoid::Criteria.new(Person)
207
+ @criteria.only(:field1)
208
+ @grouping = [{ "title" => "Sir", "group" => [{ "title" => "Sir", "age" => 30, "_type" => "Person" }] }]
209
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
210
+ end
211
+
212
+ context "when klass provided" do
213
+
214
+ before do
215
+ @reduce = "function(obj, prev) { prev.group.push(obj); }"
216
+ @collection = mock
217
+ Person.expects(:collection).returns(@collection)
218
+ end
219
+
220
+ it "calls group on the collection with the aggregate js" do
221
+ @collection.expects(:group).with(
222
+ [:field1],
223
+ {:_type => { "$in" => ["Doctor", "Person"] }},
224
+ {:group => []},
225
+ @reduce
226
+ ).returns(@grouping)
227
+ @context.group
228
+ end
229
+
230
+ end
231
+
232
+ end
233
+
234
+ describe ".initialize" do
235
+
236
+ let(:selector) { { :field => "value" } }
237
+ let(:options) { { :skip => 20 } }
238
+ let(:klass) { Person }
239
+ let(:criteria) { Mongoid::Criteria.new(klass) }
240
+ let(:context) { Mongoid::Contexts::Mongo.new(criteria) }
241
+
242
+ before do
243
+ criteria.where(selector).skip(20)
244
+ end
245
+
246
+ it "sets the selector" do
247
+ context.selector.should == criteria.selector
248
+ end
249
+
250
+ it "sets the options" do
251
+ context.options.should == options
252
+ end
253
+
254
+ it "sets the klass" do
255
+ context.klass.should == klass
256
+ end
257
+
258
+ context "when hereditary" do
259
+
260
+ it "set the selector to query across the _type when it is hereditary" do
261
+ context.selector[:_type].should == {'$in' => Person._types}
262
+ end
263
+
264
+ end
265
+
266
+ context "when not hereditary" do
267
+
268
+ before do
269
+ @criteria = Mongoid::Criteria.new(Name)
270
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
271
+ end
272
+
273
+ it "does not add the type to the selector" do
274
+ @context.selector[:_type].should be_nil
275
+ end
276
+
277
+ end
278
+
279
+ context "enslaved and cached classes" do
280
+
281
+ let(:klass) { Game }
282
+
283
+ it "enslaves the criteria" do
284
+ context.criteria.should be_enslaved
285
+ end
286
+
287
+ it "caches the criteria" do
288
+ context.criteria.should be_cached
289
+ end
290
+ end
291
+ end
292
+
293
+ describe "#iterate" do
294
+ before do
295
+ @criteria = Mongoid::Criteria.new(Person)
296
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
297
+ @person = Person.new(:title => "Sir")
298
+ @cursor = stub('cursor')
299
+ @cursor.stubs(:each).yields(@person)
300
+ end
301
+
302
+ context "when not caching" do
303
+
304
+ it "executes the criteria" do
305
+ @context.expects(:execute).returns(@cursor)
306
+ @context.iterate do |person|
307
+ person.should == @person
308
+ end
309
+
310
+ end
311
+
312
+ end
313
+
314
+ context "when caching" do
315
+ before do
316
+ @criteria.cache
317
+ end
318
+
319
+ it "executes the criteria" do
320
+ @context.expects(:execute).returns(@cursor)
321
+ @context.iterate do |person|
322
+ person.should == @person
323
+ end
324
+ end
325
+
326
+ it "executes only once and it caches the result" do
327
+ @context.expects(:execute).once.returns(@cursor)
328
+ @context.iterate do |person|
329
+ person.should == @person
330
+ end
331
+ @context.iterate do |person|
332
+ person.should == @person
333
+ end
334
+ end
335
+
336
+ it "executes even if there is no block" do
337
+ @context.expects(:execute).once.returns(@cursor)
338
+ @context.iterate
339
+ end
340
+
341
+ it "caches even if there is no block" do
342
+ @context.expects(:execute).once.returns(@cursor)
343
+ @context.iterate
344
+ @context.iterate do |person|
345
+ person.should == @person
346
+ end
347
+ end
348
+ end
349
+
350
+ end
351
+
352
+ describe "#last" do
353
+
354
+ before do
355
+ @collection = mock
356
+ Person.expects(:collection).returns(@collection)
357
+ end
358
+
359
+ context "when documents exist" do
360
+
361
+ before do
362
+ @criteria = Mongoid::Criteria.new(Person)
363
+ @criteria.order_by([[:title, :asc]])
364
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
365
+ @collection.expects(:find_one).with(
366
+ {:_type => {'$in' => ['Doctor', 'Person']}},
367
+ { :sort => [[:title, :desc]] }
368
+ ).returns(
369
+ { "title" => "Sir", "_type" => "Person" }
370
+ )
371
+ end
372
+
373
+ it "calls find on the collection with the selector and sort options reversed" do
374
+ @context.last.should be_a_kind_of(Person)
375
+ end
376
+
377
+ end
378
+
379
+ context "when no documents exist" do
380
+
381
+ before do
382
+ @criteria = Mongoid::Criteria.new(Person)
383
+ @criteria.order_by([[:_id, :asc]])
384
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
385
+ @collection.expects(:find_one).with(
386
+ {:_type => {'$in' => ['Doctor', 'Person']}},
387
+ { :sort => [[:_id, :desc]] }
388
+ ).returns(nil)
389
+ end
390
+
391
+ it "returns nil" do
392
+ @context.last.should be_nil
393
+ end
394
+
395
+ end
396
+
397
+ context "when no sorting options provided" do
398
+
399
+ before do
400
+ @criteria = Mongoid::Criteria.new(Person)
401
+ @criteria.order_by([[:_id, :asc]])
402
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
403
+ @collection.expects(:find_one).with(
404
+ {:_type => {'$in' => ['Doctor', 'Person']}},
405
+ { :sort => [[:_id, :desc]] }
406
+ ).returns(
407
+ { "title" => "Sir", "_type" => "Person" }
408
+ )
409
+ end
410
+
411
+ it "defaults to sort by id" do
412
+ @context.last
413
+ end
414
+
415
+ end
416
+
417
+ end
418
+
419
+ describe "#max" do
420
+
421
+ before do
422
+ @reduce = Mongoid::Javascript.max.gsub("[field]", "age")
423
+ @collection = mock
424
+ Person.expects(:collection).returns(@collection)
425
+ @criteria = Mongoid::Criteria.new(Person)
426
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
427
+ end
428
+
429
+ it "calls group on the collection with the aggregate js" do
430
+ @collection.expects(:group).with(
431
+ nil,
432
+ {:_type => {'$in' => ['Doctor', 'Person']}},
433
+ {:max => "start"},
434
+ @reduce
435
+ ).returns([{"max" => 200.0}])
436
+ @context.max(:age).should == 200.0
437
+ end
438
+
439
+ end
440
+
441
+ describe "#min" do
442
+
443
+ before do
444
+ @reduce = Mongoid::Javascript.min.gsub("[field]", "age")
445
+ @collection = mock
446
+ Person.expects(:collection).returns(@collection)
447
+ @criteria = Mongoid::Criteria.new(Person)
448
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
449
+ end
450
+
451
+ it "calls group on the collection with the aggregate js" do
452
+ @collection.expects(:group).with(
453
+ nil,
454
+ {:_type => {'$in' => ['Doctor', 'Person']}},
455
+ {:min => "start"},
456
+ @reduce
457
+ ).returns([{"min" => 4.0}])
458
+ @context.min(:age).should == 4.0
459
+ end
460
+
461
+ end
462
+
463
+ describe "#one" do
464
+
465
+ context "when documents exist" do
466
+
467
+ before do
468
+ Person.expects(:collection).returns(@collection)
469
+ @criteria = Mongoid::Criteria.new(Person)
470
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
471
+ @collection.expects(:find_one).with({:_type => {'$in' => ['Doctor', 'Person']}}, {}).returns(
472
+ { "title"=> "Sir", "_type" => "Person" }
473
+ )
474
+ end
475
+
476
+ it "calls find on the collection with the selector and options" do
477
+ @context.one.should be_a_kind_of(Person)
478
+ end
479
+
480
+ end
481
+
482
+ context "when no documents exist" do
483
+
484
+ before do
485
+ @collection = mock
486
+ Person.expects(:collection).returns(@collection)
487
+ @criteria = Mongoid::Criteria.new(Person)
488
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
489
+ @collection.expects(:find_one).with({:_type => {'$in' => ['Doctor', 'Person']}}, {}).returns(nil)
490
+ end
491
+
492
+ it "returns nil" do
493
+ @context.one.should be_nil
494
+ end
495
+
496
+ end
497
+
498
+ end
499
+
500
+ describe "#page" do
501
+
502
+ context "when the page option exists" do
503
+
504
+ before do
505
+ @criteria = Mongoid::Criteria.new(Person).extras({ :page => 5 })
506
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
507
+ end
508
+
509
+ it "returns the page option" do
510
+ @context.page.should == 5
511
+ end
512
+
513
+ end
514
+
515
+ context "when the page option does not exist" do
516
+
517
+ before do
518
+ @criteria = Mongoid::Criteria.new(Person)
519
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
520
+ end
521
+
522
+ it "returns 1" do
523
+ @context.page.should == 1
524
+ end
525
+
526
+ end
527
+
528
+ end
529
+
530
+ describe "#paginate" do
531
+
532
+ before do
533
+ @collection = mock
534
+ Person.expects(:collection).returns(@collection)
535
+ @criteria = Person.where(:_id => "1").skip(60).limit(20)
536
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
537
+ @collection.expects(:find).with(
538
+ {:_type => { "$in" => ["Doctor", "Person"] }, :_id => "1"}, :skip => 60, :limit => 20
539
+ ).returns([])
540
+ @results = @context.paginate
541
+ end
542
+
543
+ it "executes and paginates the results" do
544
+ @results.current_page.should == 4
545
+ @results.per_page.should == 20
546
+ end
547
+
548
+ end
549
+
550
+ describe "#paginate use last passed arguments" do
551
+ before do
552
+ @collection = mock
553
+ Person.expects(:collection).returns(@collection)
554
+ @criteria = Person.where(:_id => "1").skip(60).limit(20)
555
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
556
+ @collection.expects(:find).with(
557
+ {:_type => { "$in" => ["Doctor", "Person"] }, :_id => "1"}, :skip => 20, :limit => 10
558
+ ).returns([])
559
+ @results = @context.paginate(:page => 3, :per_page => 10)
560
+ end
561
+
562
+ it 'uses last passed per_page and page value' do
563
+ @results.current_page.should == 3
564
+ @results.per_page.should == 10
565
+ end
566
+ end
567
+
568
+ describe "#sum" do
569
+
570
+ context "when klass not provided" do
571
+
572
+ before do
573
+ @reduce = Mongoid::Javascript.sum.gsub("[field]", "age")
574
+ @collection = mock
575
+ @criteria = Mongoid::Criteria.new(Person)
576
+ @context = Mongoid::Contexts::Mongo.new(@criteria)
577
+ Person.expects(:collection).returns(@collection)
578
+ end
579
+
580
+ it "calls group on the collection with the aggregate js" do
581
+ @collection.expects(:group).with(
582
+ nil,
583
+ {:_type => {'$in' => ['Doctor', 'Person']}},
584
+ {:sum => "start"},
585
+ @reduce
586
+ ).returns([{"sum" => 50.0}])
587
+ @context.sum(:age).should == 50.0
588
+ end
589
+
590
+ end
591
+
592
+ end
593
+
594
+ context "#id_criteria" do
595
+
596
+ let(:criteria) { Mongoid::Criteria.new(Person) }
597
+ let(:context) { criteria.context }
598
+
599
+ context "with a single argument" do
600
+
601
+ let(:id) { BSON::ObjectID.new.to_s }
602
+
603
+ before do
604
+ criteria.expects(:id).with(id).returns(criteria)
605
+ end
606
+
607
+ context "when the document is found" do
608
+
609
+ let(:document) { stub }
610
+
611
+ it "returns a matching document" do
612
+ context.expects(:one).returns(document)
613
+ document.expects(:blank? => false)
614
+ context.id_criteria(id).should == document
615
+ end
616
+
617
+ end
618
+
619
+ context "when the document is not found" do
620
+
621
+ it "raises an error" do
622
+ context.expects(:one).returns(nil)
623
+ lambda { context.id_criteria(id) }.should raise_error
624
+ end
625
+
626
+ end
627
+
628
+ end
629
+
630
+ context "multiple arguments" do
631
+
632
+ context "when an array of ids" do
633
+
634
+ let(:ids) do
635
+ (0..2).inject([]) { |ary, i| ary << BSON::ObjectID.new.to_s }
636
+ end
637
+
638
+ context "when documents are found" do
639
+
640
+ let(:docs) do
641
+ (0..2).inject([]) { |ary, i| ary << stub }
642
+ end
643
+
644
+ before do
645
+ criteria.expects(:id).with(ids).returns(criteria)
646
+ end
647
+
648
+ it "returns matching documents" do
649
+ context.expects(:execute).returns(docs)
650
+ context.id_criteria(ids).should == docs
651
+ end
652
+
653
+ end
654
+
655
+ context "when documents are not found" do
656
+
657
+ it "raises an error" do
658
+ context.expects(:execute).returns([])
659
+ lambda { context.id_criteria(ids) }.should raise_error
660
+ end
661
+
662
+ end
663
+
664
+ end
665
+
666
+ context "when an array of object ids" do
667
+
668
+ let(:ids) do
669
+ (0..2).inject([]) { |ary, i| ary << BSON::ObjectID.new }
670
+ end
671
+
672
+ context "when documents are found" do
673
+
674
+ let(:docs) do
675
+ (0..2).inject([]) { |ary, i| ary << stub }
676
+ end
677
+
678
+ before do
679
+ criteria.expects(:id).with(ids).returns(criteria)
680
+ end
681
+
682
+ it "returns matching documents" do
683
+ context.expects(:execute).returns(docs)
684
+ context.id_criteria(ids).should == docs
685
+ end
686
+
687
+ end
688
+
689
+ context "when documents are not found" do
690
+
691
+ it "raises an error" do
692
+ context.expects(:execute).returns([])
693
+ lambda { context.id_criteria(ids) }.should raise_error
694
+ end
695
+
696
+ end
697
+
698
+ end
699
+ end
700
+
701
+ end
702
+
703
+ end