couch_view 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/features/couch_view.array.feature +28 -0
- data/features/couch_view.config.feature +396 -0
- data/features/couch_view.count.proxy.feature +284 -0
- data/features/couch_view.feature +359 -0
- data/features/couch_view.map.feature +117 -0
- data/features/couch_view.proxy.feature +236 -0
- data/features/setup/env.rb +15 -0
- data/features/setup/hooks.rb +7 -0
- data/features/step_definitions/couch_view.array.rb +7 -0
- data/features/step_definitions/couch_view.config.rb +11 -0
- data/features/step_definitions/couch_view.count.proxy.rb +23 -0
- data/features/step_definitions/couch_view.map.rb +19 -0
- data/features/step_definitions/couch_view.proxy.rb +15 -0
- data/features/step_definitions/couch_view.rb +87 -0
- data/lib/couch_view/array.rb +9 -0
- data/lib/couch_view/config.rb +89 -0
- data/lib/couch_view/couch_view.rb +61 -0
- data/lib/couch_view/count_proxy.rb +27 -0
- data/lib/couch_view/map.rb +45 -0
- data/lib/couch_view/map_property.rb +7 -0
- data/lib/couch_view/proxy.rb +70 -0
- data/lib/couch_view/query_options.rb +43 -0
- data/lib/couch_view.rb +10 -0
- data/readme.markdown +307 -0
- metadata +174 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: All subsets of an array
|
2
|
+
|
3
|
+
|
4
|
+
Scenario: Generating all subsets of an array
|
5
|
+
|
6
|
+
Given an array of 3 elements:
|
7
|
+
"""
|
8
|
+
@array = [1,2,3]
|
9
|
+
"""
|
10
|
+
|
11
|
+
When I call the "all_combinations" method on it:
|
12
|
+
"""
|
13
|
+
@result = @array.all_combinations
|
14
|
+
"""
|
15
|
+
|
16
|
+
Then I should receive all of the subsets of my array:
|
17
|
+
"""
|
18
|
+
@result.should == [
|
19
|
+
[],
|
20
|
+
[1],
|
21
|
+
[2],
|
22
|
+
[3],
|
23
|
+
[1,2],
|
24
|
+
[1,3],
|
25
|
+
[2,3],
|
26
|
+
[1,2,3]
|
27
|
+
]
|
28
|
+
"""
|
@@ -0,0 +1,396 @@
|
|
1
|
+
Feature: CouchView::Config
|
2
|
+
|
3
|
+
A `CouchView::Config` consists of the following data:
|
4
|
+
* a CouchView::Map
|
5
|
+
* the conditions (if any) with which to extend that map
|
6
|
+
* the names of the views
|
7
|
+
* the reduce for the view
|
8
|
+
* the base name of the view
|
9
|
+
|
10
|
+
When you instantiate a CouchView::Config, you must provide both the model and the properties to map over:
|
11
|
+
|
12
|
+
class Article < CouchRest::Model::Base; end
|
13
|
+
|
14
|
+
config = CouchView::Config.new Article
|
15
|
+
config.map :prop1, :prop2
|
16
|
+
config.view_names #==> ["by_prop1_and_prop2"]
|
17
|
+
config.base_view_name #==> "by_prop1_and_prop2"
|
18
|
+
config.model #==> Article
|
19
|
+
|
20
|
+
You could, alternatively, provide it with a model and a CouchView::Map class:
|
21
|
+
|
22
|
+
class ById; include CouchView::Map; end
|
23
|
+
config = CouchView::Config.new Article
|
24
|
+
config.map ById
|
25
|
+
config.view_names #==> ["by_id"]
|
26
|
+
config.model #==> Article
|
27
|
+
|
28
|
+
By default, a `CouchView::Config` will assume a reduce of `_count`:
|
29
|
+
|
30
|
+
config.reduce #==> "_count"
|
31
|
+
|
32
|
+
You can override this by supplying your own reduce:
|
33
|
+
|
34
|
+
config.reduce "function(key, values){}"
|
35
|
+
config.reduce #==> "function(key, values){}"
|
36
|
+
|
37
|
+
The base name of your view is generated by the parameters passed to the "map" method.
|
38
|
+
|
39
|
+
If you want to override that, you can pass a new name to the "base_view_name" method:
|
40
|
+
|
41
|
+
config.base_view_name "funny"
|
42
|
+
|
43
|
+
Lastly, you can provide your `CouchView::Config` with conditions:
|
44
|
+
|
45
|
+
module Published
|
46
|
+
def conditions
|
47
|
+
"#{super} && doc.published == true"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
config.conditions Published
|
52
|
+
config.conditions #==> [Published]
|
53
|
+
|
54
|
+
You could also add conditions by passing a block to the map method:
|
55
|
+
|
56
|
+
config.map :label do
|
57
|
+
conditions Published
|
58
|
+
end
|
59
|
+
|
60
|
+
You can now ask your `Config` to return a hash containing all of the views (with their corresponding map/reduce) that you should setup on your model:
|
61
|
+
|
62
|
+
class Article < CouchRest::Model::Base
|
63
|
+
property :label
|
64
|
+
property :published, TrueClass, :default => false
|
65
|
+
end
|
66
|
+
|
67
|
+
config = CouchView::Config.new Article
|
68
|
+
config.map :label
|
69
|
+
|
70
|
+
module Published
|
71
|
+
def conditions
|
72
|
+
"#{super} && doc.published == true"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
config.conditions Published
|
77
|
+
|
78
|
+
config.views #==>
|
79
|
+
{
|
80
|
+
"by_label" => {
|
81
|
+
"map" => "function....",
|
82
|
+
"reduce" => "_count"
|
83
|
+
},
|
84
|
+
"by_label_published" => {
|
85
|
+
"map" => "function....",
|
86
|
+
"reduce" => "_count"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
@db
|
92
|
+
Scenario: Generating a name based on the properties passed in to map over
|
93
|
+
|
94
|
+
Given the following model:
|
95
|
+
"""
|
96
|
+
class Article < CouchRest::Model::Base
|
97
|
+
include CouchView
|
98
|
+
property :label
|
99
|
+
property :name
|
100
|
+
end
|
101
|
+
"""
|
102
|
+
|
103
|
+
When I create a CouchView::Config to map over Article labels:
|
104
|
+
"""
|
105
|
+
@config = CouchView::Config.new Article
|
106
|
+
@config.map :label
|
107
|
+
"""
|
108
|
+
|
109
|
+
Then the config should report "by_label" as a view name:
|
110
|
+
"""
|
111
|
+
@config.view_names.should == ["by_label"]
|
112
|
+
"""
|
113
|
+
|
114
|
+
When I create a CouchView::Config to map over Article labels and names:
|
115
|
+
"""
|
116
|
+
@config = CouchView::Config.new Article
|
117
|
+
@config.map :label, :name
|
118
|
+
"""
|
119
|
+
|
120
|
+
Then the config should report "by_label" as a view name:
|
121
|
+
"""
|
122
|
+
@config.view_names.should == ["by_label_and_name"]
|
123
|
+
"""
|
124
|
+
|
125
|
+
When I create a CouchView::Map `ById`:
|
126
|
+
"""
|
127
|
+
class ById
|
128
|
+
include CouchView::Map
|
129
|
+
end
|
130
|
+
"""
|
131
|
+
|
132
|
+
And I create a CouchView::Config to map over article documents `ById`:
|
133
|
+
"""
|
134
|
+
@config = CouchView::Config.new Article
|
135
|
+
@config.map ById
|
136
|
+
"""
|
137
|
+
|
138
|
+
Then the config should report "by_id" as a view name:
|
139
|
+
"""
|
140
|
+
@config.view_names.should == ["by_id"]
|
141
|
+
"""
|
142
|
+
|
143
|
+
|
144
|
+
@db
|
145
|
+
Scenario: Setting a custom reduce
|
146
|
+
|
147
|
+
Given the following model:
|
148
|
+
"""
|
149
|
+
class Article < CouchRest::Model::Base
|
150
|
+
include CouchView
|
151
|
+
property :label
|
152
|
+
property :name
|
153
|
+
end
|
154
|
+
"""
|
155
|
+
|
156
|
+
When I create a CouchView::Config to map over Article labels:
|
157
|
+
"""
|
158
|
+
@config = CouchView::Config.new Article
|
159
|
+
@config.map :label
|
160
|
+
"""
|
161
|
+
|
162
|
+
Then the config should default the "reduce" to "_count":
|
163
|
+
"""
|
164
|
+
@config.reduce.should == "_count"
|
165
|
+
"""
|
166
|
+
|
167
|
+
When I change the "reduce" to a javascript function:
|
168
|
+
"""
|
169
|
+
@config.reduce "function(key, values){}"
|
170
|
+
"""
|
171
|
+
|
172
|
+
Then the config should return that function for the "reduce":
|
173
|
+
"""
|
174
|
+
@config.reduce.should == "function(key, values){}"
|
175
|
+
"""
|
176
|
+
|
177
|
+
|
178
|
+
@db
|
179
|
+
Scenario: Setting conditions on the view
|
180
|
+
|
181
|
+
Given the following model:
|
182
|
+
"""
|
183
|
+
class Article < CouchRest::Model::Base
|
184
|
+
include CouchView
|
185
|
+
property :label
|
186
|
+
property :name
|
187
|
+
end
|
188
|
+
"""
|
189
|
+
|
190
|
+
And the following conditions:
|
191
|
+
"""
|
192
|
+
module Published
|
193
|
+
def conditions
|
194
|
+
"#{super} && doc.published == true"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
module Visible
|
199
|
+
def conditions
|
200
|
+
"#{super} && doc.visible == true"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
"""
|
204
|
+
|
205
|
+
When I create a CouchView::Config to map over Article labels:
|
206
|
+
"""
|
207
|
+
@config = CouchView::Config.new Article
|
208
|
+
@config.map :label
|
209
|
+
"""
|
210
|
+
|
211
|
+
And I add the Published and Visible conditions to it:
|
212
|
+
"""
|
213
|
+
@config.conditions Published, Visible
|
214
|
+
"""
|
215
|
+
|
216
|
+
Then the conditions should be Published and Visible:
|
217
|
+
"""
|
218
|
+
@config.conditions.should == [Published, Visible]
|
219
|
+
"""
|
220
|
+
|
221
|
+
And the view names should include views for published, visible, and published/visible documents:
|
222
|
+
"""
|
223
|
+
@config.view_names.sort.should == ["by_label", "by_label_published", "by_label_published_visible", "by_label_visible"]
|
224
|
+
"""
|
225
|
+
|
226
|
+
|
227
|
+
@db @focus
|
228
|
+
Scenario: Creating conditions by passing a block to the map
|
229
|
+
|
230
|
+
Given the following model:
|
231
|
+
"""
|
232
|
+
class Article < CouchRest::Model::Base; end
|
233
|
+
"""
|
234
|
+
|
235
|
+
And the following conditions:
|
236
|
+
"""
|
237
|
+
module Published
|
238
|
+
def conditions
|
239
|
+
"#{super} && doc.published == true"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
module Visible
|
244
|
+
def conditions
|
245
|
+
"#{super} && doc.visible == true"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
"""
|
249
|
+
|
250
|
+
When I create a view config and specify conditions in a block on the `map` method:
|
251
|
+
"""
|
252
|
+
@config = CouchView::Config.new Article
|
253
|
+
@config.map :label do
|
254
|
+
conditions Published, Visible
|
255
|
+
end
|
256
|
+
"""
|
257
|
+
|
258
|
+
Then the conditions method on my config should return the conditions specified:
|
259
|
+
"""
|
260
|
+
@config.conditions.should == [Published, Visible]
|
261
|
+
"""
|
262
|
+
|
263
|
+
@db
|
264
|
+
Scenario: Getting all the views
|
265
|
+
|
266
|
+
Given the following model:
|
267
|
+
"""
|
268
|
+
class Article < CouchRest::Model::Base
|
269
|
+
include CouchView
|
270
|
+
property :label
|
271
|
+
property :name
|
272
|
+
end
|
273
|
+
"""
|
274
|
+
|
275
|
+
And the following conditions:
|
276
|
+
"""
|
277
|
+
module Published
|
278
|
+
def conditions
|
279
|
+
"#{super} && doc.published == true"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
module Visible
|
284
|
+
def conditions
|
285
|
+
"#{super} && doc.visible == true"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
"""
|
289
|
+
|
290
|
+
When I create a CouchView::Config to map over Article labels:
|
291
|
+
"""
|
292
|
+
@config = CouchView::Config.new Article
|
293
|
+
@config.map :label
|
294
|
+
"""
|
295
|
+
|
296
|
+
And I add the Published and Visible conditions to it:
|
297
|
+
"""
|
298
|
+
@config.conditions Published, Visible
|
299
|
+
"""
|
300
|
+
|
301
|
+
Then the views should include a "by_label" view:
|
302
|
+
"""
|
303
|
+
@config.views[:by_label][:map].should ==
|
304
|
+
"
|
305
|
+
function(doc){
|
306
|
+
if (doc['couchrest-type'] == 'Article')
|
307
|
+
emit(doc.label, null)
|
308
|
+
}
|
309
|
+
"
|
310
|
+
@config.views[:by_label][:reduce].should == "_count"
|
311
|
+
"""
|
312
|
+
|
313
|
+
And the views should include a "by_label_published" view:
|
314
|
+
"""
|
315
|
+
@config.views[:by_label_published][:map].should ==
|
316
|
+
"
|
317
|
+
function(doc){
|
318
|
+
if (doc['couchrest-type'] == 'Article' && doc.published == true)
|
319
|
+
emit(doc.label, null)
|
320
|
+
}
|
321
|
+
"
|
322
|
+
@config.views[:by_label_published][:reduce].should == "_count"
|
323
|
+
"""
|
324
|
+
|
325
|
+
And the views should include a "by_label_visible" view:
|
326
|
+
"""
|
327
|
+
@config.views[:by_label_visible][:map].should ==
|
328
|
+
"
|
329
|
+
function(doc){
|
330
|
+
if (doc['couchrest-type'] == 'Article' && doc.visible == true)
|
331
|
+
emit(doc.label, null)
|
332
|
+
}
|
333
|
+
"
|
334
|
+
@config.views[:by_label_visible][:reduce].should == "_count"
|
335
|
+
"""
|
336
|
+
|
337
|
+
And the views should include a "by_label_published_visible" view:
|
338
|
+
"""
|
339
|
+
@config.views[:by_label_published_visible][:map].should ==
|
340
|
+
"
|
341
|
+
function(doc){
|
342
|
+
if (doc['couchrest-type'] == 'Article' && doc.published == true && doc.visible == true)
|
343
|
+
emit(doc.label, null)
|
344
|
+
}
|
345
|
+
"
|
346
|
+
@config.views[:by_label_published_visible][:reduce].should == "_count"
|
347
|
+
"""
|
348
|
+
|
349
|
+
|
350
|
+
@db @focus
|
351
|
+
Scenario: Giving your view a custom base name
|
352
|
+
|
353
|
+
Given the following model:
|
354
|
+
"""
|
355
|
+
class Article < CouchRest::Model::Base
|
356
|
+
include CouchView
|
357
|
+
property :label
|
358
|
+
property :name
|
359
|
+
end
|
360
|
+
"""
|
361
|
+
|
362
|
+
And the following conditions:
|
363
|
+
"""
|
364
|
+
module Published
|
365
|
+
def conditions
|
366
|
+
"#{super} && doc.published == true"
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
module Visible
|
371
|
+
def conditions
|
372
|
+
"#{super} && doc.visible == true"
|
373
|
+
end
|
374
|
+
end
|
375
|
+
"""
|
376
|
+
|
377
|
+
When I create a CouchView::Config to map over Article labels:
|
378
|
+
"""
|
379
|
+
@config = CouchView::Config.new Article
|
380
|
+
@config.map :label
|
381
|
+
"""
|
382
|
+
|
383
|
+
And I give it a base name of "funny":
|
384
|
+
"""
|
385
|
+
@config.base_view_name "funny"
|
386
|
+
"""
|
387
|
+
|
388
|
+
And I add the Published and Visible conditions to it:
|
389
|
+
"""
|
390
|
+
@config.conditions Published, Visible
|
391
|
+
"""
|
392
|
+
|
393
|
+
Then the view names should include "funny" views for published, visible, and published/visible documents:
|
394
|
+
"""
|
395
|
+
@config.view_names.sort.should == ["funny", "funny_published", "funny_published_visible", "funny_visible"]
|
396
|
+
"""
|
@@ -0,0 +1,284 @@
|
|
1
|
+
Feature: CouchView::Count::Proxy
|
2
|
+
|
3
|
+
A `CouchView::Count::Proxy` is like a regular `CouchView::Proxy`, except that it defaults the CouchDB "reduce" option to "true".
|
4
|
+
|
5
|
+
proxy = CouchView::Count::Proxy SomeModel, :some_view
|
6
|
+
proxy._options #==> { "reduce" => true }
|
7
|
+
|
8
|
+
Another noticable difference: you can't call ".each" on the proxy unless you've set the "group" option to "true":
|
9
|
+
|
10
|
+
proxy = CouchView::Count::Proxy SomeModel, :some_view
|
11
|
+
|
12
|
+
proxy.each {...} #==> raises an exception "You can't call 'each' on a count proxy that doesn't set 'group' to 'true'."
|
13
|
+
|
14
|
+
If you've set "group" to true, then when you call ".each" on it, you will iterate over the key/value pairs in the response:
|
15
|
+
|
16
|
+
proxy.group(true).each do |key, value|
|
17
|
+
...
|
18
|
+
end
|
19
|
+
|
20
|
+
If you'd rather work with the raw (hash) response on a group level query, simply use the "get!" method:
|
21
|
+
|
22
|
+
proxy.get!
|
23
|
+
|
24
|
+
If you're not running a group level query, then "get!" will return the actual count (`Fixnum`):
|
25
|
+
|
26
|
+
proxy = CouchView::Count::Proxy SomeModel, :some_view
|
27
|
+
proxy.get! #==> 0, or some other positive integer
|
28
|
+
|
29
|
+
|
30
|
+
@db
|
31
|
+
Scenario: Options default to "reduce" => true
|
32
|
+
|
33
|
+
Given an Article model with a view "by_id":
|
34
|
+
"""
|
35
|
+
class Article < CouchRest::Model::Base
|
36
|
+
view_by :id
|
37
|
+
end
|
38
|
+
"""
|
39
|
+
|
40
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_id":
|
41
|
+
"""
|
42
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_id
|
43
|
+
"""
|
44
|
+
|
45
|
+
Then the options on the proxy should default to "reduce" => true
|
46
|
+
"""
|
47
|
+
@proxy._options.should == {:reduce => true}
|
48
|
+
"""
|
49
|
+
|
50
|
+
|
51
|
+
@db
|
52
|
+
Scenario: ".each" should iterate over the key/value pairs of the 'rows' result:
|
53
|
+
|
54
|
+
Given the following map definition:
|
55
|
+
"""
|
56
|
+
class ByLabel
|
57
|
+
include CouchView::Map
|
58
|
+
|
59
|
+
def map
|
60
|
+
"
|
61
|
+
function(doc){
|
62
|
+
if (#{conditions})
|
63
|
+
emit(doc.label, null)
|
64
|
+
}
|
65
|
+
"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
"""
|
69
|
+
|
70
|
+
And an Article model that maps ByLabel:
|
71
|
+
"""
|
72
|
+
class Article < CouchRest::Model::Base
|
73
|
+
include CouchView
|
74
|
+
map ByLabel
|
75
|
+
end
|
76
|
+
"""
|
77
|
+
|
78
|
+
And several articles:
|
79
|
+
"""
|
80
|
+
Article.create :label => "fun-article"
|
81
|
+
Article.create :label => "awesome-article"
|
82
|
+
Article.create :label => "awesome-article"
|
83
|
+
"""
|
84
|
+
|
85
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_id":
|
86
|
+
"""
|
87
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_by_label
|
88
|
+
"""
|
89
|
+
|
90
|
+
And I set the CouchDB "group" query option to "true":
|
91
|
+
"""
|
92
|
+
@proxy.group! true
|
93
|
+
"""
|
94
|
+
|
95
|
+
Then the ".each" method should iterate over the keys and values in the 'rows' array in the query response:
|
96
|
+
"""
|
97
|
+
@results = []
|
98
|
+
@proxy.each {|label, count| @results << {label => count}}
|
99
|
+
@results.first.should == {"awesome-article" => 2}
|
100
|
+
@results.last.should == {"fun-article" => 1}
|
101
|
+
@results.count.should == 2
|
102
|
+
"""
|
103
|
+
|
104
|
+
|
105
|
+
@db @focus
|
106
|
+
Scenario: ".get!" should return 0 when the reduce returns an empty 'rows' response:
|
107
|
+
|
108
|
+
Given the following map definition:
|
109
|
+
"""
|
110
|
+
class ByLabel
|
111
|
+
include CouchView::Map
|
112
|
+
|
113
|
+
def map
|
114
|
+
"
|
115
|
+
function(doc){
|
116
|
+
if (#{conditions})
|
117
|
+
emit(doc.label, null)
|
118
|
+
}
|
119
|
+
"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
"""
|
123
|
+
|
124
|
+
And an Article model that maps ByLabel:
|
125
|
+
"""
|
126
|
+
class Article < CouchRest::Model::Base
|
127
|
+
include CouchView
|
128
|
+
map ByLabel
|
129
|
+
end
|
130
|
+
"""
|
131
|
+
|
132
|
+
And there are no articles:
|
133
|
+
"""
|
134
|
+
Article.all.count.should == 0
|
135
|
+
"""
|
136
|
+
|
137
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_id":
|
138
|
+
"""
|
139
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_by_label
|
140
|
+
"""
|
141
|
+
|
142
|
+
Then the ".get!" method should return 0:
|
143
|
+
"""
|
144
|
+
@proxy.get!.should == 0
|
145
|
+
"""
|
146
|
+
|
147
|
+
|
148
|
+
@db @focus
|
149
|
+
Scenario: ".get!" should return the 'value' of the first row of the 'rows' reduce response:
|
150
|
+
|
151
|
+
Given the following map definition:
|
152
|
+
"""
|
153
|
+
class ById
|
154
|
+
include CouchView::Map
|
155
|
+
end
|
156
|
+
"""
|
157
|
+
|
158
|
+
And an Article model that maps ByLabel:
|
159
|
+
"""
|
160
|
+
class Article < CouchRest::Model::Base
|
161
|
+
include CouchView
|
162
|
+
map ById
|
163
|
+
end
|
164
|
+
"""
|
165
|
+
|
166
|
+
And there are 2 articles:
|
167
|
+
"""
|
168
|
+
2.times { Article.create }
|
169
|
+
"""
|
170
|
+
|
171
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_by_id":
|
172
|
+
"""
|
173
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_by_id
|
174
|
+
"""
|
175
|
+
|
176
|
+
Then the ".get!" method should return 2:
|
177
|
+
"""
|
178
|
+
@proxy.get!.should == 2
|
179
|
+
"""
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
@db @focus
|
184
|
+
Scenario: ".get!" should return the raw JSON (hash) response from CouchDB for a group query:
|
185
|
+
|
186
|
+
Given the following map definition:
|
187
|
+
"""
|
188
|
+
class ByLabel
|
189
|
+
include CouchView::Map
|
190
|
+
|
191
|
+
def map
|
192
|
+
"
|
193
|
+
function(doc){
|
194
|
+
if (#{conditions})
|
195
|
+
emit(doc.label, null)
|
196
|
+
}
|
197
|
+
"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
"""
|
201
|
+
|
202
|
+
And an Article model that maps ByLabel:
|
203
|
+
"""
|
204
|
+
class Article < CouchRest::Model::Base
|
205
|
+
include CouchView
|
206
|
+
map ByLabel
|
207
|
+
end
|
208
|
+
"""
|
209
|
+
|
210
|
+
And several articles:
|
211
|
+
"""
|
212
|
+
Article.create :label => "fun-article"
|
213
|
+
Article.create :label => "awesome-article"
|
214
|
+
Article.create :label => "awesome-article"
|
215
|
+
"""
|
216
|
+
|
217
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_id":
|
218
|
+
"""
|
219
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_by_label
|
220
|
+
"""
|
221
|
+
|
222
|
+
And I set the CouchDB "group" query option to "true":
|
223
|
+
"""
|
224
|
+
@proxy.group! true
|
225
|
+
"""
|
226
|
+
|
227
|
+
Then the ".get!" method should return the raw JSON response from CouchDB as a hash:
|
228
|
+
"""
|
229
|
+
@proxy.get!.should == {
|
230
|
+
"rows" => [
|
231
|
+
{ "key" => "awesome-article", "value" => 2 },
|
232
|
+
{ "key" => "fun-article", "value" => 1 }
|
233
|
+
]
|
234
|
+
}
|
235
|
+
"""
|
236
|
+
|
237
|
+
|
238
|
+
@db
|
239
|
+
Scenario: You can't call ".each" on a count proxy unless the CouchDB "group" option is set to true
|
240
|
+
|
241
|
+
Given the following map definition:
|
242
|
+
"""
|
243
|
+
class ByLabel
|
244
|
+
include CouchView::Map
|
245
|
+
|
246
|
+
def map
|
247
|
+
"
|
248
|
+
function(doc){
|
249
|
+
if (#{conditions})
|
250
|
+
emit(doc.label, null)
|
251
|
+
}
|
252
|
+
"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
"""
|
256
|
+
|
257
|
+
And an Article model that maps ByLabel:
|
258
|
+
"""
|
259
|
+
class Article < CouchRest::Model::Base
|
260
|
+
include CouchView
|
261
|
+
map ByLabel
|
262
|
+
end
|
263
|
+
"""
|
264
|
+
|
265
|
+
When I instantiate a new CouchView::Map::Proxy with "Article" and ":by_label":
|
266
|
+
"""
|
267
|
+
@proxy = CouchView::Count::Proxy.new Article, :by_by_label
|
268
|
+
"""
|
269
|
+
|
270
|
+
Then ".each" should raise an exception:
|
271
|
+
"""
|
272
|
+
proc { @proxy.each {|k,v|} }.should raise_exception("You can't call 'each' on a count proxy that doesn't set 'group' to 'true'.")
|
273
|
+
"""
|
274
|
+
|
275
|
+
When I set the CouchDB "group" query option to "true":
|
276
|
+
"""
|
277
|
+
@proxy.group!(true)
|
278
|
+
"""
|
279
|
+
|
280
|
+
Then ".each" should not raise an exception:
|
281
|
+
"""
|
282
|
+
proc { @proxy.each {|k,v|} }.should_not raise_exception
|
283
|
+
"""
|
284
|
+
|