mongodoc 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/Rakefile +21 -0
  2. data/TODO +6 -1
  3. data/VERSION +1 -1
  4. data/features/finders.feature +1 -1
  5. data/features/mongodoc_base.feature +11 -2
  6. data/features/{named_scopes.feature → scopes.feature} +0 -0
  7. data/features/step_definitions/document_steps.rb +15 -4
  8. data/features/step_definitions/documents.rb +3 -3
  9. data/features/step_definitions/query_steps.rb +17 -14
  10. data/features/step_definitions/{named_scope_steps.rb → scope_steps.rb} +0 -0
  11. data/features/using_criteria.feature +22 -43
  12. data/lib/mongodoc.rb +1 -1
  13. data/lib/mongodoc/associations/collection_proxy.rb +3 -1
  14. data/lib/mongodoc/associations/document_proxy.rb +4 -1
  15. data/lib/mongodoc/associations/hash_proxy.rb +3 -1
  16. data/lib/mongodoc/associations/proxy_base.rb +6 -4
  17. data/lib/mongodoc/attributes.rb +6 -6
  18. data/lib/mongodoc/contexts.rb +24 -0
  19. data/lib/mongodoc/contexts/enumerable.rb +132 -0
  20. data/lib/mongodoc/contexts/mongo.rb +215 -0
  21. data/lib/mongodoc/criteria.rb +36 -479
  22. data/lib/mongodoc/document.rb +3 -2
  23. data/lib/mongodoc/finders.rb +31 -11
  24. data/lib/mongodoc/matchers.rb +35 -0
  25. data/lib/mongodoc/scope.rb +64 -0
  26. data/lib/mongoid/contexts/paging.rb +42 -0
  27. data/lib/mongoid/criteria.rb +264 -0
  28. data/lib/mongoid/criterion/complex.rb +21 -0
  29. data/lib/mongoid/criterion/exclusion.rb +65 -0
  30. data/lib/mongoid/criterion/inclusion.rb +92 -0
  31. data/lib/mongoid/criterion/optional.rb +136 -0
  32. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  33. data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
  34. data/lib/mongoid/matchers/all.rb +11 -0
  35. data/lib/mongoid/matchers/default.rb +26 -0
  36. data/lib/mongoid/matchers/exists.rb +13 -0
  37. data/lib/mongoid/matchers/gt.rb +11 -0
  38. data/lib/mongoid/matchers/gte.rb +11 -0
  39. data/lib/mongoid/matchers/in.rb +11 -0
  40. data/lib/mongoid/matchers/lt.rb +11 -0
  41. data/lib/mongoid/matchers/lte.rb +11 -0
  42. data/lib/mongoid/matchers/ne.rb +11 -0
  43. data/lib/mongoid/matchers/nin.rb +11 -0
  44. data/lib/mongoid/matchers/size.rb +11 -0
  45. data/mongodoc.gemspec +39 -9
  46. data/spec/attributes_spec.rb +16 -2
  47. data/spec/contexts/enumerable_spec.rb +335 -0
  48. data/spec/contexts/mongo_spec.rb +148 -0
  49. data/spec/contexts_spec.rb +28 -0
  50. data/spec/criteria_spec.rb +15 -766
  51. data/spec/finders_spec.rb +28 -36
  52. data/spec/matchers_spec.rb +342 -0
  53. data/spec/scope_spec.rb +79 -0
  54. metadata +40 -10
  55. data/features/step_definitions/criteria_steps.rb +0 -42
  56. data/lib/mongodoc/named_scope.rb +0 -68
  57. data/spec/named_scope_spec.rb +0 -82
@@ -7,73 +7,65 @@ describe MongoDoc::Finders do
7
7
  key :data
8
8
  end
9
9
 
10
- context ".criteria" do
11
- it "creates a new criteria for the document" do
12
- FindersTest.criteria.should be_a_kind_of(MongoDoc::Criteria)
13
- end
14
-
15
- it "sets the criteria klass" do
16
- FindersTest.criteria.klass.should == FindersTest
17
- end
18
- end
10
+ let(:criteria) { stub('criteria').as_null_object }
19
11
 
20
12
  context ".find" do
21
13
  before do
22
- @criteria = stub('criteria').as_null_object
23
- @conditions = {:where => 'this.a > 3'}
24
- MongoDoc::Criteria.stub(:translate).and_return(@criteria)
14
+ FindersTest.stub(:criteria).and_return(criteria)
25
15
  end
26
16
 
27
- it "creates a criteria" do
28
- MongoDoc::Criteria.should_receive(:translate).with(FindersTest, @conditions).and_return(@criteria)
29
- FindersTest.find(:first, @conditions)
17
+ it "delegates to id for the criteria" do
18
+ args = [1, 2, 3]
19
+ criteria.should_receive(:id).with(*args)
20
+ FindersTest.find(*args)
30
21
  end
22
+ end
31
23
 
32
- [:all, :first, :last].each do |which|
33
- it "calls #{which} on the criteria" do
34
- @criteria.should_receive(which)
35
- FindersTest.find(which, @conditions)
36
- end
24
+ context ".find_all" do
25
+ it "delegates to an empty criteria" do
26
+ FindersTest.should_receive(:criteria)
27
+ FindersTest.find_all
28
+ end
29
+
30
+ it "returns the empty criteria" do
31
+ FindersTest.stub(:criteria).and_return(criteria)
32
+ FindersTest.find_all.should == criteria
37
33
  end
38
34
  end
39
35
 
40
36
  context ".find_one" do
41
37
  context "with an id" do
42
- it "calls translate with the id" do
38
+ it "delegates to translate" do
43
39
  id = 'an id'
44
- MongoDoc::Criteria.should_receive(:translate).with(FindersTest, id)
40
+ Mongoid::Criteria.should_receive(:translate).with(FindersTest, id)
45
41
  FindersTest.find_one(id)
46
42
  end
47
43
  end
48
44
 
49
45
  context "with conditions" do
50
- before do
51
- @criteria = stub('criteria').as_null_object
52
- @conditions = {:where => 'this.a > 3'}
53
- end
46
+ let(:conditions) { {:where => 'this.a > 3'} }
54
47
 
55
48
  it "calls translate with the conditions" do
56
- MongoDoc::Criteria.should_receive(:translate).with(FindersTest, @conditions).and_return(@criteria)
57
- FindersTest.find_one(@conditions)
49
+ Mongoid::Criteria.should_receive(:translate).with(FindersTest, conditions).and_return(criteria)
50
+ FindersTest.find_one(conditions)
58
51
  end
59
52
 
60
- it "call :one on the result" do
61
- MongoDoc::Criteria.stub(:translate).and_return(@criteria)
62
- @criteria.should_receive(:one)
63
- FindersTest.find_one(@conditions)
53
+ it "call one on the result" do
54
+ Mongoid::Criteria.stub(:translate).and_return(criteria)
55
+ criteria.should_receive(:one)
56
+ FindersTest.find_one(conditions)
64
57
  end
65
58
  end
66
59
  end
67
60
 
68
61
  context "all other finders" do
69
62
  before do
70
- @criteria = stub('criteria').as_null_object
71
- MongoDoc::Criteria.stub(:new).and_return(@criteria)
63
+ FindersTest.stub(:criteria).and_return(criteria)
72
64
  end
73
65
 
74
- [:all, :count, :first, :last].each do |which|
66
+ %w(count first last).each do |which|
75
67
  it "calls #{which} on the new criteria" do
76
- @criteria.should_receive(which)
68
+ criteria.should_receive(which)
77
69
  FindersTest.send(which)
78
70
  end
79
71
  end
@@ -0,0 +1,342 @@
1
+ require "spec_helper"
2
+
3
+ describe MongoDoc::Matchers do
4
+
5
+ class Address
6
+ include MongoDoc::Matchers
7
+
8
+ attr_accessor :number
9
+ attr_accessor :services
10
+ attr_accessor :street
11
+
12
+ def initialize(attrs = {})
13
+ attrs.each {|key, value| send("#{key}=", value)}
14
+ end
15
+ end
16
+
17
+ describe "#matches?" do
18
+
19
+ context "when performing simple matching" do
20
+
21
+ before do
22
+ @document = Address.new(:street => "Clarkenwell Road")
23
+ end
24
+
25
+ context "when the attributes match" do
26
+
27
+ before do
28
+ @selector = { :street => "Clarkenwell Road" }
29
+ end
30
+
31
+ it "returns true" do
32
+ @document.matches?(@selector).should be_true
33
+ end
34
+
35
+ end
36
+
37
+ context "when the attributes dont match" do
38
+
39
+ before do
40
+ @selector = { :street => "Broadway Ave" }
41
+ end
42
+
43
+ it "returns false" do
44
+ @document.matches?(@selector).should be_false
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ context "when performing complex matching" do
52
+
53
+ before do
54
+ @document = Address.new(:services => ["first", "second"], :number => 100)
55
+ end
56
+
57
+ context "with an $all selector" do
58
+
59
+ context "when the attributes match" do
60
+
61
+ before do
62
+ @selector = { :services => { "$all" => [ "first", "second" ] } }
63
+ end
64
+
65
+ it "returns true" do
66
+ @document.matches?(@selector).should be_true
67
+ end
68
+
69
+ end
70
+
71
+ context "when the attributes do not match" do
72
+
73
+ before do
74
+ @selector = { :services => { "$all" => [ "first" ] } }
75
+ end
76
+
77
+ it "returns false" do
78
+ @document.matches?(@selector).should be_false
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ context "with an $exists selector" do
86
+
87
+ context "when the attributes match" do
88
+
89
+ before do
90
+ @selector = { :services => { "$exists" => true } }
91
+ end
92
+
93
+ it "returns true" do
94
+ @document.matches?(@selector).should be_true
95
+ end
96
+
97
+ end
98
+
99
+ context "when the attributes do not match" do
100
+
101
+ before do
102
+ @selector = { :services => { "$exists" => false } }
103
+ end
104
+
105
+ it "returns false" do
106
+ @document.matches?(@selector).should be_false
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
113
+ context "with a $gt selector" do
114
+
115
+ context "when the attributes match" do
116
+
117
+ before do
118
+ @selector = { :number => { "$gt" => 50 } }
119
+ end
120
+
121
+ it "returns true" do
122
+ @document.matches?(@selector).should be_true
123
+ end
124
+
125
+ end
126
+
127
+ context "when the attributes do not match" do
128
+
129
+ before do
130
+ @selector = { :number => { "$gt" => 200 } }
131
+ end
132
+
133
+ it "returns false" do
134
+ @document.matches?(@selector).should be_false
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ context "with a $gte selector" do
142
+
143
+ context "when the attributes match" do
144
+
145
+ before do
146
+ @selector = { :number => { "$gte" => 100 } }
147
+ end
148
+
149
+ it "returns true" do
150
+ @document.matches?(@selector).should be_true
151
+ end
152
+
153
+ end
154
+
155
+ context "when the attributes do not match" do
156
+
157
+ before do
158
+ @selector = { :number => { "$gte" => 200 } }
159
+ end
160
+
161
+ it "returns false" do
162
+ @document.matches?(@selector).should be_false
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+
169
+ context "with an $in selector" do
170
+
171
+ context "when the attributes match" do
172
+
173
+ before do
174
+ @selector = { :number => { "$in" => [ 100, 200 ] } }
175
+ end
176
+
177
+ it "returns true" do
178
+ @document.matches?(@selector).should be_true
179
+ end
180
+
181
+ end
182
+
183
+ context "when the attributes do not match" do
184
+
185
+ before do
186
+ @selector = { :number => { "$in" => [ 200, 300 ] } }
187
+ end
188
+
189
+ it "returns false" do
190
+ @document.matches?(@selector).should be_false
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
197
+ context "with a $lt selector" do
198
+
199
+ context "when the attributes match" do
200
+
201
+ before do
202
+ @selector = { :number => { "$lt" => 200 } }
203
+ end
204
+
205
+ it "returns true" do
206
+ @document.matches?(@selector).should be_true
207
+ end
208
+
209
+ end
210
+
211
+ context "when the attributes do not match" do
212
+
213
+ before do
214
+ @selector = { :number => { "$lt" => 50 } }
215
+ end
216
+
217
+ it "returns false" do
218
+ @document.matches?(@selector).should be_false
219
+ end
220
+
221
+ end
222
+
223
+ end
224
+
225
+ context "with a $lte selector" do
226
+
227
+ context "when the attributes match" do
228
+
229
+ before do
230
+ @selector = { :number => { "$lte" => 200 } }
231
+ end
232
+
233
+ it "returns true" do
234
+ @document.matches?(@selector).should be_true
235
+ end
236
+
237
+ end
238
+
239
+ context "when the attributes do not match" do
240
+
241
+ before do
242
+ @selector = { :number => { "$lte" => 50 } }
243
+ end
244
+
245
+ it "returns false" do
246
+ @document.matches?(@selector).should be_false
247
+ end
248
+
249
+ end
250
+
251
+ end
252
+
253
+ context "with an $ne selector" do
254
+
255
+ context "when the attributes match" do
256
+
257
+ before do
258
+ @selector = { :number => { "$ne" => 200 } }
259
+ end
260
+
261
+ it "returns true" do
262
+ @document.matches?(@selector).should be_true
263
+ end
264
+
265
+ end
266
+
267
+ context "when the attributes do not match" do
268
+
269
+ before do
270
+ @selector = { :number => { "$ne" => 100 } }
271
+ end
272
+
273
+ it "returns false" do
274
+ @document.matches?(@selector).should be_false
275
+ end
276
+
277
+ end
278
+
279
+ end
280
+
281
+ context "with a $nin selector" do
282
+
283
+ context "when the attributes match" do
284
+
285
+ before do
286
+ @selector = { :number => { "$nin" => [ 1, 2, 3 ] } }
287
+ end
288
+
289
+ it "returns true" do
290
+ @document.matches?(@selector).should be_true
291
+ end
292
+
293
+ end
294
+
295
+ context "when the attributes do not match" do
296
+
297
+ before do
298
+ @selector = { :number => { "$nin" => [ 100 ] } }
299
+ end
300
+
301
+ it "returns false" do
302
+ @document.matches?(@selector).should be_false
303
+ end
304
+
305
+ end
306
+
307
+ end
308
+
309
+ context "with a $size selector" do
310
+
311
+ context "when the attributes match" do
312
+
313
+ before do
314
+ @selector = { :services => { "$size" => 2 } }
315
+ end
316
+
317
+ it "returns true" do
318
+ @document.matches?(@selector).should be_true
319
+ end
320
+
321
+ end
322
+
323
+ context "when the attributes do not match" do
324
+
325
+ before do
326
+ @selector = { :services => { "$size" => 5 } }
327
+ end
328
+
329
+ it "returns false" do
330
+ @document.matches?(@selector).should be_false
331
+ end
332
+
333
+ end
334
+
335
+ end
336
+
337
+ end
338
+
339
+ end
340
+
341
+ end
342
+
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper.rb"))
2
+
3
+ describe MongoDoc::Scope do
4
+
5
+ module Extension
6
+ def extension_module_method
7
+ "extension module method"
8
+ end
9
+ end
10
+
11
+ class ScopeTest
12
+ include MongoDoc::Document
13
+
14
+ key :active
15
+ key :count
16
+
17
+ scope :active, where(:active => true)
18
+ scope :count_lte_one, where(:count.lte => 1) do
19
+ def extension_method
20
+ "extension method"
21
+ end
22
+ end
23
+ scope :count_gt_one, where(:count.gt => 1), :extend => Extension
24
+ scope :at_least_count, lambda {|count| where(:count.gt => count)}
25
+ end
26
+
27
+ context ".scope" do
28
+ it "adds the named scope to the hash of scopes" do
29
+ ScopeTest.scopes.should have_key(:active)
30
+ end
31
+
32
+ it "creates a class method for the named scope" do
33
+ ScopeTest.should respond_to(:active)
34
+ end
35
+ end
36
+
37
+ context "accessing a named scope" do
38
+ it "is a criteria proxy" do
39
+ MongoDoc::Scope::CriteriaProxy.should === ScopeTest.active
40
+ end
41
+
42
+ it "responds like a criteria" do
43
+ ScopeTest.active.should respond_to(:selector)
44
+ end
45
+
46
+ it "has set the conditions on the criteria" do
47
+ ScopeTest.active.selector.should has_entry(:active => true)
48
+ end
49
+
50
+ it "sets the association extension by block" do
51
+ ScopeTest.count_lte_one.extension_method.should == "extension method"
52
+ end
53
+
54
+ it "sets the association extension by :extend" do
55
+ ScopeTest.count_gt_one.extension_module_method.should == "extension module method"
56
+ end
57
+
58
+ context "when using a lambda" do
59
+ it "accepts parameters to the criteria" do
60
+ ScopeTest.at_least_count(3).selector.should has_entry(:count => {'$gt' => 3})
61
+ end
62
+ end
63
+ end
64
+
65
+ context "chained scopes" do
66
+ it "is a criteria proxy" do
67
+ MongoDoc::Scope::CriteriaProxy.should === ScopeTest.active.count_gt_one
68
+ end
69
+
70
+ it "responds like a criteria" do
71
+ ScopeTest.active.count_gt_one.should respond_to(:selector)
72
+ end
73
+
74
+ it "merges the criteria" do
75
+ ScopeTest.active.count_gt_one.selector.should has_entry(:count => {'$gt' => 1}, :active => true)
76
+ end
77
+ end
78
+ end
79
+