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,25 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Contexts do
4
+
5
+ context ".context_for" do
6
+ let(:klass) { stub('klass', :embedded? => false) }
7
+ let(:criteria) { stub('criteria', :klass => klass) }
8
+
9
+ context "when criteria is for a top-level Mongoid::Document" do
10
+ it "creates a Mongo context" do
11
+ Mongoid::Contexts::Mongo.expects(:new).with(criteria)
12
+ Mongoid::Contexts.context_for(criteria)
13
+ end
14
+ end
15
+
16
+ context "when criteria is for an embedded Mongoid::Document" do
17
+ it "creates a Mongo context" do
18
+ klass.stubs(:embedded?).returns(true)
19
+ Mongoid::Contexts::Enumerable.expects(:new).with(criteria)
20
+ Mongoid::Contexts.context_for(criteria)
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,873 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria do
4
+
5
+ before do
6
+ @criteria = Mongoid::Criteria.new(Person)
7
+ @canvas_criteria = Mongoid::Criteria.new(Canvas)
8
+ end
9
+
10
+ describe "#+" do
11
+
12
+ before do
13
+ @sir = Person.new(:title => "Sir")
14
+ @canvas = Canvas.new
15
+ end
16
+
17
+ context "when the criteria has not been executed" do
18
+
19
+ before do
20
+ @collection = mock
21
+ @cursor = stub(:count => 1)
22
+ @cursor.expects(:each).at_least_once.yields(@sir)
23
+ Person.expects(:collection).at_least_once.returns(@collection)
24
+ @collection.expects(:find).at_least_once.returns(@cursor)
25
+ end
26
+
27
+ it "executes the criteria and concats the results" do
28
+ results = @criteria + [ @canvas ]
29
+ results.should == [ @sir, @canvas ]
30
+ end
31
+
32
+ end
33
+
34
+ context "when the other is a criteria" do
35
+
36
+ before do
37
+ @collection = mock
38
+ @canvas_collection = mock
39
+ @cursor = stub(:count => 1)
40
+ @canvas_cursor = stub(:count => 1)
41
+ @cursor.expects(:each).at_least_once.yields(@sir)
42
+ @canvas_cursor.expects(:each).at_least_once.yields(@canvas)
43
+ Person.expects(:collection).at_least_once.returns(@collection)
44
+ @collection.expects(:find).at_least_once.returns(@cursor)
45
+ Canvas.expects(:collection).at_least_once.returns(@canvas_collection)
46
+ @canvas_collection.expects(:find).at_least_once.returns(@canvas_cursor)
47
+ end
48
+
49
+ it "concats the results" do
50
+ results = @criteria + @canvas_criteria
51
+ results.should == [ @sir, @canvas ]
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ describe "#-" do
59
+
60
+ before do
61
+ @sir = Person.new(:title => "Sir")
62
+ @madam = Person.new(:title => "Madam")
63
+ end
64
+
65
+ context "when the criteria has not been executed" do
66
+
67
+ before do
68
+ @collection = mock
69
+ @cursor = stub(:count => 1)
70
+ @cursor.expects(:each).yields(@madam)
71
+ Person.expects(:collection).returns(@collection)
72
+ @collection.expects(:find).returns(@cursor)
73
+ end
74
+
75
+ it "executes the criteria and returns the difference" do
76
+ results = @criteria - [ @sir ]
77
+ results.should == [ @madam ]
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ describe "#[]" do
85
+
86
+ before do
87
+ @criteria.where(:title => "Sir")
88
+ @collection = stub
89
+ @person = Person.new(:title => "Sir")
90
+ @cursor = stub(:count => 10)
91
+ @cursor.expects(:each).yields(@person)
92
+ end
93
+
94
+ context "when the criteria has not been executed" do
95
+
96
+ before do
97
+ Person.expects(:collection).returns(@collection)
98
+ @collection.expects(:find).with({ :title => "Sir", :_type => { "$in" => ["Doctor", "Person"] } }, {}).returns(@cursor)
99
+ end
100
+
101
+ it "executes the criteria and returns the element at the index" do
102
+ @criteria[0].should == @person
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ describe "#aggregate" do
110
+
111
+ before do
112
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
113
+ @criteria.instance_variable_set(:@context, @context)
114
+ end
115
+
116
+ it "delegates to the context" do
117
+ @context.expects(:aggregate)
118
+ @criteria.aggregate
119
+ end
120
+
121
+ end
122
+
123
+ describe "#avg" do
124
+
125
+ before do
126
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
127
+ @criteria.instance_variable_set(:@context, @context)
128
+ end
129
+
130
+ it "delegates to the context" do
131
+ @context.expects(:avg).with(:age)
132
+ @criteria.avg(:age)
133
+ end
134
+ end
135
+
136
+ describe "#blank?" do
137
+
138
+ before do
139
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
140
+ @criteria.instance_variable_set(:@context, @context)
141
+ end
142
+
143
+ context "when the context is blank" do
144
+
145
+ before do
146
+ @context.expects(:blank?).returns(true)
147
+ end
148
+
149
+ it "returns true" do
150
+ @criteria.blank?.should be_true
151
+ end
152
+ end
153
+
154
+ context "when the context is not blank" do
155
+
156
+ before do
157
+ @context.expects(:blank?).returns(false)
158
+ end
159
+
160
+ it "returns false" do
161
+ @criteria.blank?.should be_false
162
+ end
163
+ end
164
+ end
165
+
166
+ describe "#context" do
167
+
168
+ context "when the context has been set" do
169
+
170
+ before do
171
+ @context = stub
172
+ @criteria.instance_variable_set(:@context, @context)
173
+ end
174
+
175
+ it "returns the memoized context" do
176
+ @criteria.context.should == @context
177
+ end
178
+
179
+ end
180
+
181
+ context "when the context has not been set" do
182
+
183
+ before do
184
+ @context = stub
185
+ end
186
+
187
+ it "creates a new context" do
188
+ Mongoid::Contexts::Mongo.expects(:new).with(@criteria).returns(@context)
189
+ @criteria.context.should == @context
190
+ end
191
+
192
+ end
193
+
194
+ context "when the class is embedded" do
195
+
196
+ before do
197
+ @criteria = Mongoid::Criteria.new(Address)
198
+ end
199
+
200
+ it "returns an enumerable context" do
201
+ @criteria.context.should be_a_kind_of(Mongoid::Contexts::Enumerable)
202
+ end
203
+
204
+ end
205
+
206
+ context "when the class is not embedded" do
207
+
208
+ it "returns a mongo context" do
209
+ @criteria.context.should be_a_kind_of(Mongoid::Contexts::Mongo)
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+
216
+ describe "#distinct" do
217
+
218
+ before do
219
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
220
+ @criteria.instance_variable_set(:@context, @context)
221
+ end
222
+
223
+ it "delegates to the context" do
224
+ @context.expects(:distinct).with(:title)
225
+ @criteria.distinct(:title)
226
+ end
227
+ end
228
+
229
+ describe "#entries" do
230
+
231
+ context "filtering" do
232
+
233
+ before do
234
+ @collection = mock
235
+ Person.expects(:collection).returns(@collection)
236
+ @criteria = Mongoid::Criteria.new(Person).extras(:page => 1, :per_page => 20)
237
+ @collection.expects(:find).with(@criteria.selector, @criteria.options).returns([])
238
+ end
239
+
240
+ it "filters out unused params" do
241
+ @criteria.entries
242
+ @criteria.options[:page].should be_nil
243
+ @criteria.options[:per_page].should be_nil
244
+ end
245
+
246
+ end
247
+
248
+ context "when type is :all" do
249
+
250
+ before do
251
+ @collection = mock
252
+ Person.expects(:collection).returns(@collection)
253
+ @criteria = Mongoid::Criteria.new(Person).extras(:page => 1, :per_page => 20)
254
+ @cursor = stub(:count => 44)
255
+ @cursor.expects(:each)
256
+ @collection.expects(:find).with(@criteria.selector, @criteria.options).returns(@cursor)
257
+ end
258
+
259
+ it "does not add the count instance variable" do
260
+ @criteria.entries.should == []
261
+ @criteria.instance_variable_get(:@count).should be_nil
262
+ end
263
+
264
+ end
265
+
266
+ context "when type is not :first" do
267
+
268
+ it "calls find on the collection with the selector and options" do
269
+ criteria = Mongoid::Criteria.new(Person)
270
+ collection = mock
271
+ Person.expects(:collection).returns(collection)
272
+ collection.expects(:find).with(criteria.selector, criteria.options).returns([])
273
+ criteria.entries.should == []
274
+ end
275
+
276
+ end
277
+
278
+ end
279
+
280
+ describe "#count" do
281
+
282
+ before do
283
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
284
+ @criteria.instance_variable_set(:@context, @context)
285
+ end
286
+
287
+ it "delegates to the context" do
288
+ @context.expects(:count).returns(10)
289
+ @criteria.count.should == 10
290
+ end
291
+
292
+ end
293
+
294
+ describe "#exists?" do
295
+
296
+ before do
297
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
298
+ @criteria.instance_variable_set(:@context, @context)
299
+ end
300
+
301
+ it "call the count context and return true if there are element" do
302
+ @context.expects(:count).returns(10)
303
+ @criteria.exists?.should be_true
304
+ end
305
+
306
+ it "call the count context and return false if there are no element" do
307
+ @context.expects(:count).returns(0)
308
+ @criteria.exists?.should be_false
309
+ end
310
+
311
+ end
312
+
313
+ describe "#each" do
314
+
315
+ before do
316
+ @criteria.where(:title => "Sir")
317
+ @collection = stub
318
+ @person = Person.new(:title => "Sir")
319
+ @cursor = stub(:count => 10)
320
+ end
321
+
322
+ it "delegates to the context#iterate" do
323
+ @context = stub('context')
324
+ @criteria.stubs(:context).returns(@context)
325
+ @context.expects(:iterate)
326
+ @criteria.each
327
+ end
328
+
329
+ context "when the criteria has not been executed" do
330
+
331
+ before do
332
+ Person.expects(:collection).returns(@collection)
333
+ @collection.expects(:find).with({ :_type => { "$in" => ["Doctor", "Person"] }, :title => "Sir" }, {}).returns(@cursor)
334
+ @cursor.expects(:each).yields(@person)
335
+ end
336
+
337
+ it "executes the criteria" do
338
+ @criteria.each do |doc|
339
+ doc.should == @person
340
+ end
341
+ end
342
+
343
+ end
344
+
345
+ context "when the criteria has been executed" do
346
+
347
+ before do
348
+ Person.expects(:collection).returns(@collection)
349
+ @collection.expects(:find).with({ :_type => { "$in" => ["Doctor", "Person"] }, :title => "Sir" }, {}).returns(@cursor)
350
+ @cursor.expects(:each).yields(@person)
351
+ end
352
+
353
+ it "calls each on the existing results" do
354
+ @criteria.each do |person|
355
+ person.should == @person
356
+ end
357
+ end
358
+
359
+ end
360
+
361
+ context "when no block is passed" do
362
+
363
+ it "returns self" do
364
+ @criteria.each.should == @criteria
365
+ end
366
+
367
+ end
368
+
369
+ context "when caching" do
370
+
371
+ before do
372
+ Person.expects(:collection).returns(@collection)
373
+ @collection.expects(:find).with(
374
+ { :_type => { "$in" => ["Doctor", "Person"] },
375
+ :title => "Sir"
376
+ },
377
+ { :cache => true }
378
+ ).returns(@cursor)
379
+ @cursor.expects(:each).yields(@person)
380
+ @criteria.cache
381
+ @criteria.each do |doc|
382
+ doc.should == @person
383
+ end
384
+ end
385
+
386
+ it "caches the results of the cursor iteration" do
387
+ @criteria.each do |doc|
388
+ doc.should == @person
389
+ end
390
+ # Do it again for sanity's sake.
391
+ @criteria.each do |doc|
392
+ doc.should == @person
393
+ end
394
+ end
395
+
396
+ end
397
+
398
+ end
399
+
400
+ describe "#first" do
401
+
402
+ before do
403
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
404
+ @criteria.instance_variable_set(:@context, @context)
405
+ end
406
+
407
+ it "delegates to the context" do
408
+ @context.expects(:first).returns([])
409
+ @criteria.first.should == []
410
+ end
411
+
412
+ end
413
+
414
+ describe "#group" do
415
+
416
+ before do
417
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
418
+ @criteria.instance_variable_set(:@context, @context)
419
+ end
420
+
421
+ it "delegates to the context" do
422
+ @context.expects(:group).returns({})
423
+ @criteria.group.should == {}
424
+ end
425
+
426
+ end
427
+
428
+ describe "#initialize" do
429
+
430
+ let(:criteria) { Mongoid::Criteria.new(Person) }
431
+
432
+ it "sets the selector to an empty hash" do
433
+ criteria.selector.should == {}
434
+ end
435
+
436
+ it "sets the options to an empty hash" do
437
+ criteria.options.should == {}
438
+ end
439
+
440
+ it "sets the documents to an empty array" do
441
+ criteria.documents.should == []
442
+ end
443
+
444
+ it "sets the klass to the given class" do
445
+ criteria.klass.should == Person
446
+ end
447
+
448
+ end
449
+
450
+ describe "#last" do
451
+
452
+ before do
453
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
454
+ @criteria.instance_variable_set(:@context, @context)
455
+ end
456
+
457
+ it "delegates to the context" do
458
+ @context.expects(:last).returns([])
459
+ @criteria.last.should == []
460
+ end
461
+
462
+ end
463
+
464
+ describe "#max" do
465
+
466
+ before do
467
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
468
+ @criteria.instance_variable_set(:@context, @context)
469
+ end
470
+
471
+ it "delegates to the context" do
472
+ @context.expects(:max).with(:field).returns(100)
473
+ @criteria.max(:field).should == 100
474
+ end
475
+
476
+ end
477
+
478
+ describe "#merge" do
479
+
480
+ before do
481
+ @criteria.where(:title => "Sir", :age => 30).skip(40).limit(20)
482
+ end
483
+
484
+ context "with another criteria" do
485
+
486
+ context "when the other has a selector and options" do
487
+
488
+ before do
489
+ @other = Mongoid::Criteria.new(Person)
490
+ @other.where(:name => "Chloe").order_by([[:name, :asc]])
491
+ @selector = { :title => "Sir", :age => 30, :name => "Chloe" }
492
+ @options = { :skip => 40, :limit => 20, :sort => [[:name, :asc]] }
493
+ end
494
+
495
+ it "merges the selector and options hashes together" do
496
+ @criteria.merge(@other)
497
+ @criteria.selector.should == @selector
498
+ @criteria.options.should == @options
499
+ end
500
+
501
+ end
502
+
503
+ context "when the other has no selector or options" do
504
+
505
+ before do
506
+ @other = Mongoid::Criteria.new(Person)
507
+ @selector = { :title => "Sir", :age => 30 }
508
+ @options = { :skip => 40, :limit => 20 }
509
+ end
510
+
511
+ it "merges the selector and options hashes together" do
512
+ @criteria.merge(@other)
513
+ @criteria.selector.should == @selector
514
+ @criteria.options.should == @options
515
+ end
516
+
517
+ end
518
+
519
+ context "when the other has a document collection" do
520
+
521
+ before do
522
+ @documents = [ stub ]
523
+ @other = Mongoid::Criteria.new(Person)
524
+ @other.documents = @documents
525
+ end
526
+
527
+ it "merges the documents collection in" do
528
+ @criteria.merge(@other)
529
+ @criteria.documents.should == @documents
530
+ end
531
+
532
+ end
533
+
534
+ end
535
+
536
+ end
537
+
538
+ describe "#method_missing" do
539
+
540
+ before do
541
+ @criteria = Mongoid::Criteria.new(Person)
542
+ @criteria.where(:title => "Sir")
543
+ end
544
+
545
+ it "merges the criteria with the next one" do
546
+ @new_criteria = @criteria.accepted
547
+ @new_criteria.selector.should == { :title => "Sir", :terms => true }
548
+ end
549
+
550
+ context "chaining more than one scope" do
551
+
552
+ before do
553
+ @criteria = Person.accepted.old.knight
554
+ end
555
+
556
+ it "returns the final merged criteria" do
557
+ @criteria.selector.should == { :title => "Sir", :terms => true, :age => { "$gt" => 50 } }
558
+ end
559
+
560
+ end
561
+
562
+ context "when returning a non-criteria object" do
563
+ let(:ages) { [10, 20] }
564
+ it "does not attempt to merge" do
565
+ Person.stubs(:ages => ages)
566
+ expect { @criteria.ages }.to_not raise_error(NoMethodError)
567
+ end
568
+ end
569
+
570
+ context "when expecting behaviour of an array" do
571
+
572
+ before do
573
+ @array = mock
574
+ @document = mock
575
+ end
576
+
577
+ describe "#[]" do
578
+
579
+ it "collects the criteria and calls []" do
580
+ @criteria.expects(:entries).returns([@document])
581
+ @criteria[0].should == @document
582
+ end
583
+
584
+ end
585
+
586
+ describe "#rand" do
587
+
588
+ it "collects the criteria and call rand" do
589
+ @criteria.expects(:entries).returns(@array)
590
+ @array.expects(:send).with(:rand).returns(@document)
591
+ @criteria.rand
592
+ end
593
+
594
+ end
595
+
596
+ end
597
+
598
+ end
599
+
600
+ describe "#min" do
601
+
602
+ before do
603
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
604
+ @criteria.instance_variable_set(:@context, @context)
605
+ end
606
+
607
+ it "delegates to the context" do
608
+ @context.expects(:min).with(:field).returns(100)
609
+ @criteria.min(:field).should == 100
610
+ end
611
+
612
+ end
613
+
614
+ describe "#offset" do
615
+
616
+ end
617
+
618
+ describe "#one" do
619
+
620
+ before do
621
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
622
+ @criteria.instance_variable_set(:@context, @context)
623
+ end
624
+
625
+ it "delegates to the context" do
626
+ @context.expects(:one)
627
+ @criteria.one
628
+ end
629
+
630
+ end
631
+
632
+ describe "#page" do
633
+
634
+ before do
635
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
636
+ @criteria.instance_variable_set(:@context, @context)
637
+ end
638
+
639
+ it "delegates to the context" do
640
+ @context.expects(:page).returns(1)
641
+ @criteria.page.should == 1
642
+ end
643
+
644
+ end
645
+
646
+ describe "#paginate" do
647
+
648
+ before do
649
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
650
+ @criteria.instance_variable_set(:@context, @context)
651
+ end
652
+
653
+ it "delegates to the context" do
654
+ @context.expects(:paginate).returns([])
655
+ @criteria.paginate.should == []
656
+ end
657
+
658
+ end
659
+
660
+ describe "#per_page" do
661
+
662
+ before do
663
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
664
+ @criteria.instance_variable_set(:@context, @context)
665
+ end
666
+
667
+ it "delegates to the context" do
668
+ @context.expects(:per_page).returns(20)
669
+ @criteria.per_page.should == 20
670
+ end
671
+
672
+ end
673
+
674
+ describe "#scoped" do
675
+
676
+ context "when the options contain sort criteria" do
677
+
678
+ before do
679
+ @criteria = Person.where(:title => "Sir").asc(:score)
680
+ end
681
+
682
+ it "changes sort to order_by" do
683
+ @criteria.scoped.should == { :where => { :title => "Sir" }, :order_by => [[:score, :asc]] }
684
+ end
685
+ end
686
+
687
+ end
688
+
689
+ describe "#sum" do
690
+
691
+ before do
692
+ @context = stub.quacks_like(Mongoid::Contexts::Mongo.allocate)
693
+ @criteria.instance_variable_set(:@context, @context)
694
+ end
695
+
696
+ it "delegates to the context" do
697
+ @context.expects(:sum).with(:field).returns(20)
698
+ @criteria.sum(:field).should == 20
699
+ end
700
+
701
+ end
702
+
703
+ describe ".translate" do
704
+
705
+ context "with a single argument" do
706
+
707
+ context "when the arg is a string" do
708
+
709
+ before do
710
+ @id = BSON::ObjectID.new.to_s
711
+ @document = stub
712
+ @criteria = mock
713
+ Person.expects(:criteria).returns(@criteria)
714
+ end
715
+
716
+ it "delegates to #id_criteria" do
717
+ @criteria.expects(:id_criteria).with(@id).returns(@document)
718
+ Mongoid::Criteria.translate(Person, @id).should == @document
719
+ end
720
+ end
721
+
722
+ context "when the arg is an object id" do
723
+
724
+ before do
725
+ @id = BSON::ObjectID.new
726
+ @document = stub
727
+ @criteria = mock
728
+ Person.expects(:criteria).returns(@criteria)
729
+ end
730
+
731
+ it "delegates to #id_criteria" do
732
+ @criteria.expects(:id_criteria).with(@id).returns(@document)
733
+ Mongoid::Criteria.translate(Person, @id).should == @document
734
+ end
735
+ end
736
+ end
737
+
738
+ context "multiple arguments" do
739
+
740
+ context "when an array of ids" do
741
+
742
+ before do
743
+ @ids = []
744
+ @documents = []
745
+ 3.times do
746
+ @ids << BSON::ObjectID.new.to_s
747
+ @documents << stub
748
+ end
749
+ @criteria = mock
750
+ Person.expects(:criteria).returns(@criteria)
751
+ end
752
+
753
+ it "delegates to #id_criteria" do
754
+ @criteria.expects(:id_criteria).with(@ids).returns(@documents)
755
+ Mongoid::Criteria.translate(Person, @ids).should == @documents
756
+ end
757
+
758
+ end
759
+
760
+ context "when Person, :conditions => {}" do
761
+
762
+ before do
763
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
764
+ end
765
+
766
+ it "returns a criteria with a selector from the conditions" do
767
+ @criteria.selector.should == { :title => "Test" }
768
+ end
769
+
770
+ it "returns a criteria with klass Person" do
771
+ @criteria.klass.should == Person
772
+ end
773
+
774
+ end
775
+
776
+ context "when Person, :conditions => {:id => id}" do
777
+
778
+ before do
779
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :id => "1234e567" })
780
+ end
781
+
782
+ it "returns a criteria with a selector from the conditions" do
783
+ @criteria.selector.should == { :_id => "1234e567" }
784
+ end
785
+
786
+ it "returns a criteria with klass Person" do
787
+ @criteria.klass.should == Person
788
+ end
789
+
790
+ end
791
+
792
+ context "when :all, :conditions => {}" do
793
+
794
+ before do
795
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
796
+ end
797
+
798
+ it "returns a criteria with a selector from the conditions" do
799
+ @criteria.selector.should == { :title => "Test" }
800
+ end
801
+
802
+ it "returns a criteria with klass Person" do
803
+ @criteria.klass.should == Person
804
+ end
805
+
806
+ end
807
+
808
+ context "when :last, :conditions => {}" do
809
+
810
+ before do
811
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" })
812
+ end
813
+
814
+ it "returns a criteria with a selector from the conditions" do
815
+ @criteria.selector.should == { :title => "Test" }
816
+ end
817
+
818
+ it "returns a criteria with klass Person" do
819
+ @criteria.klass.should == Person
820
+ end
821
+ end
822
+
823
+ context "when options are provided" do
824
+
825
+ before do
826
+ @criteria = Mongoid::Criteria.translate(Person, :conditions => { :title => "Test" }, :skip => 10)
827
+ end
828
+
829
+ it "adds the criteria and the options" do
830
+ @criteria.selector.should == { :title => "Test" }
831
+ @criteria.options.should == { :skip => 10 }
832
+ end
833
+
834
+ end
835
+
836
+ end
837
+
838
+ end
839
+
840
+ context "#fuse" do
841
+
842
+ it ":where => {:title => 'Test'} returns a criteria with the correct selector" do
843
+ @result = @criteria.fuse(:where => { :title => 'Test' })
844
+ @result.selector[:title].should == 'Test'
845
+ end
846
+
847
+ it ":where => {:title => 'Test'}, :skip => 10 returns a criteria with the correct selector and options" do
848
+ @result = @criteria.fuse(:where => { :title => 'Test' }, :skip => 10)
849
+ @result.selector[:title].should == 'Test'
850
+ @result.options.should == { :skip => 10 }
851
+ end
852
+ end
853
+
854
+ context "===" do
855
+
856
+ context "when the other object is a Criteria" do
857
+ subject { Mongoid::Criteria === Mongoid::Criteria.allocate }
858
+ it { should be_true }
859
+ end
860
+
861
+ context "when the other object is a Scope" do
862
+ subject { Mongoid::Criteria === Mongoid::Scope.allocate }
863
+ it { should be_true }
864
+ end
865
+
866
+ context "when the other object is not compatible" do
867
+ subject { Mongoid::Criteria === [] }
868
+ it { should be_false }
869
+ end
870
+
871
+ end
872
+
873
+ end