samlown-couchrest 0.35

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +46 -0
  3. data/Rakefile +67 -0
  4. data/THANKS.md +19 -0
  5. data/examples/model/example.rb +144 -0
  6. data/examples/word_count/markov +38 -0
  7. data/examples/word_count/views/books/chunked-map.js +3 -0
  8. data/examples/word_count/views/books/united-map.js +1 -0
  9. data/examples/word_count/views/markov/chain-map.js +6 -0
  10. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  11. data/examples/word_count/views/word_count/count-map.js +6 -0
  12. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  13. data/examples/word_count/word_count.rb +46 -0
  14. data/examples/word_count/word_count_query.rb +40 -0
  15. data/examples/word_count/word_count_views.rb +26 -0
  16. data/history.txt +114 -0
  17. data/lib/couchrest/commands/generate.rb +71 -0
  18. data/lib/couchrest/commands/push.rb +103 -0
  19. data/lib/couchrest/core/adapters/restclient.rb +35 -0
  20. data/lib/couchrest/core/database.rb +377 -0
  21. data/lib/couchrest/core/design.rb +79 -0
  22. data/lib/couchrest/core/document.rb +84 -0
  23. data/lib/couchrest/core/http_abstraction.rb +48 -0
  24. data/lib/couchrest/core/response.rb +16 -0
  25. data/lib/couchrest/core/rest_api.rb +49 -0
  26. data/lib/couchrest/core/server.rb +88 -0
  27. data/lib/couchrest/core/view.rb +4 -0
  28. data/lib/couchrest/helper/pager.rb +103 -0
  29. data/lib/couchrest/helper/streamer.rb +51 -0
  30. data/lib/couchrest/helper/upgrade.rb +51 -0
  31. data/lib/couchrest/middlewares/logger.rb +263 -0
  32. data/lib/couchrest/mixins/attachments.rb +31 -0
  33. data/lib/couchrest/mixins/attribute_protection.rb +74 -0
  34. data/lib/couchrest/mixins/callbacks.rb +532 -0
  35. data/lib/couchrest/mixins/class_proxy.rb +124 -0
  36. data/lib/couchrest/mixins/collection.rb +260 -0
  37. data/lib/couchrest/mixins/design_doc.rb +103 -0
  38. data/lib/couchrest/mixins/document_queries.rb +80 -0
  39. data/lib/couchrest/mixins/extended_attachments.rb +70 -0
  40. data/lib/couchrest/mixins/extended_document_mixins.rb +9 -0
  41. data/lib/couchrest/mixins/properties.rb +154 -0
  42. data/lib/couchrest/mixins/validation.rb +246 -0
  43. data/lib/couchrest/mixins/views.rb +173 -0
  44. data/lib/couchrest/mixins.rb +4 -0
  45. data/lib/couchrest/monkeypatches.rb +113 -0
  46. data/lib/couchrest/more/casted_model.rb +58 -0
  47. data/lib/couchrest/more/extended_document.rb +310 -0
  48. data/lib/couchrest/more/property.rb +50 -0
  49. data/lib/couchrest/more/typecast.rb +175 -0
  50. data/lib/couchrest/support/blank.rb +42 -0
  51. data/lib/couchrest/support/class.rb +190 -0
  52. data/lib/couchrest/support/rails.rb +42 -0
  53. data/lib/couchrest/validation/auto_validate.rb +157 -0
  54. data/lib/couchrest/validation/contextual_validators.rb +78 -0
  55. data/lib/couchrest/validation/validation_errors.rb +125 -0
  56. data/lib/couchrest/validation/validators/absent_field_validator.rb +74 -0
  57. data/lib/couchrest/validation/validators/confirmation_validator.rb +107 -0
  58. data/lib/couchrest/validation/validators/format_validator.rb +122 -0
  59. data/lib/couchrest/validation/validators/formats/email.rb +66 -0
  60. data/lib/couchrest/validation/validators/formats/url.rb +43 -0
  61. data/lib/couchrest/validation/validators/generic_validator.rb +120 -0
  62. data/lib/couchrest/validation/validators/length_validator.rb +139 -0
  63. data/lib/couchrest/validation/validators/method_validator.rb +89 -0
  64. data/lib/couchrest/validation/validators/numeric_validator.rb +109 -0
  65. data/lib/couchrest/validation/validators/required_field_validator.rb +114 -0
  66. data/lib/couchrest.rb +162 -0
  67. data/spec/couchrest/core/couchrest_spec.rb +184 -0
  68. data/spec/couchrest/core/database_spec.rb +840 -0
  69. data/spec/couchrest/core/design_spec.rb +138 -0
  70. data/spec/couchrest/core/document_spec.rb +275 -0
  71. data/spec/couchrest/core/server_spec.rb +35 -0
  72. data/spec/couchrest/helpers/pager_spec.rb +122 -0
  73. data/spec/couchrest/helpers/streamer_spec.rb +52 -0
  74. data/spec/couchrest/more/attribute_protection_spec.rb +150 -0
  75. data/spec/couchrest/more/casted_extended_doc_spec.rb +79 -0
  76. data/spec/couchrest/more/casted_model_spec.rb +406 -0
  77. data/spec/couchrest/more/extended_doc_attachment_spec.rb +135 -0
  78. data/spec/couchrest/more/extended_doc_inherited_spec.rb +40 -0
  79. data/spec/couchrest/more/extended_doc_spec.rb +797 -0
  80. data/spec/couchrest/more/extended_doc_subclass_spec.rb +98 -0
  81. data/spec/couchrest/more/extended_doc_view_spec.rb +456 -0
  82. data/spec/couchrest/more/property_spec.rb +628 -0
  83. data/spec/fixtures/attachments/README +3 -0
  84. data/spec/fixtures/attachments/couchdb.png +0 -0
  85. data/spec/fixtures/attachments/test.html +11 -0
  86. data/spec/fixtures/more/article.rb +35 -0
  87. data/spec/fixtures/more/card.rb +22 -0
  88. data/spec/fixtures/more/cat.rb +20 -0
  89. data/spec/fixtures/more/course.rb +22 -0
  90. data/spec/fixtures/more/event.rb +8 -0
  91. data/spec/fixtures/more/invoice.rb +17 -0
  92. data/spec/fixtures/more/person.rb +9 -0
  93. data/spec/fixtures/more/question.rb +6 -0
  94. data/spec/fixtures/more/service.rb +12 -0
  95. data/spec/fixtures/more/user.rb +22 -0
  96. data/spec/fixtures/views/lib.js +3 -0
  97. data/spec/fixtures/views/test_view/lib.js +3 -0
  98. data/spec/fixtures/views/test_view/only-map.js +4 -0
  99. data/spec/fixtures/views/test_view/test-map.js +3 -0
  100. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  101. data/spec/spec.opts +6 -0
  102. data/spec/spec_helper.rb +49 -0
  103. data/utils/remap.rb +27 -0
  104. data/utils/subset.rb +30 -0
  105. metadata +223 -0
@@ -0,0 +1,138 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Design do
4
+
5
+ describe "defining a view" do
6
+ it "should add a view to the design doc" do
7
+ @des = CouchRest::Design.new
8
+ method = @des.view_by :name
9
+ method.should == "by_name"
10
+ @des["views"]["by_name"].should_not be_nil
11
+ end
12
+ end
13
+
14
+ describe "with an unsaved view" do
15
+ before(:each) do
16
+ @des = CouchRest::Design.new
17
+ @des.view_by :name
18
+ end
19
+ it "should accept a name" do
20
+ @des.name = "mytest"
21
+ @des.name.should == "mytest"
22
+ end
23
+ it "should not save on view definition" do
24
+ @des.rev.should be_nil
25
+ end
26
+ it "should freak out on view access" do
27
+ lambda{@des.view :by_name}.should raise_error
28
+ end
29
+ end
30
+
31
+ describe "saving" do
32
+ before(:each) do
33
+ @des = CouchRest::Design.new
34
+ @des.view_by :name
35
+ @des.database = reset_test_db!
36
+ end
37
+ it "should fail without a name" do
38
+ lambda{@des.save}.should raise_error(ArgumentError)
39
+ end
40
+ it "should work with a name" do
41
+ @des.name = "myview"
42
+ @des.save
43
+ end
44
+ end
45
+
46
+ describe "when it's saved" do
47
+ before(:each) do
48
+ @db = reset_test_db!
49
+ @db.bulk_save([{"name" => "x"},{"name" => "y"}])
50
+ @des = CouchRest::Design.new
51
+ @des.database = @db
52
+ @des.view_by :name
53
+ end
54
+ it "should by queryable when it's saved" do
55
+ @des.name = "mydesign"
56
+ @des.save
57
+ res = @des.view :by_name
58
+ res["rows"][0]["key"].should == "x"
59
+ end
60
+ it "should be queryable on specified database" do
61
+ @des.name = "mydesign"
62
+ @des.save
63
+ @des.database = nil
64
+ res = @des.view_on @db, :by_name
65
+ res["rows"][0]["key"].should == "x"
66
+ end
67
+ end
68
+
69
+ describe "from a saved document" do
70
+ before(:each) do
71
+ @db = reset_test_db!
72
+ @db.save_doc({
73
+ "_id" => "_design/test",
74
+ "views" => {
75
+ "by_name" => {
76
+ "map" => "function(doc){if (doc.name) emit(doc.name, null)}"
77
+ }
78
+ }
79
+ })
80
+ @db.bulk_save([{"name" => "a"},{"name" => "b"}])
81
+ @des = @db.get "_design/test"
82
+ end
83
+ it "should be a Design" do
84
+ @des.should be_an_instance_of(CouchRest::Design)
85
+ end
86
+ it "should have a modifiable name" do
87
+ @des.name.should == "test"
88
+ @des.name = "supertest"
89
+ @des.id.should == "_design/supertest"
90
+ end
91
+ it "should by queryable" do
92
+ res = @des.view :by_name
93
+ res["rows"][0]["key"].should == "a"
94
+ end
95
+ end
96
+
97
+ describe "a view with default options" do
98
+ before(:all) do
99
+ @db = reset_test_db!
100
+ @des = CouchRest::Design.new
101
+ @des.name = "test"
102
+ @des.view_by :name, :descending => true
103
+ @des.database = @db
104
+ @des.save
105
+ @db.bulk_save([{"name" => "a"},{"name" => "z"}])
106
+ end
107
+ it "should save them" do
108
+ @d2 = @db.get(@des.id)
109
+ @d2["views"]["by_name"]["couchrest-defaults"].should == {"descending"=>true}
110
+ end
111
+ it "should use them" do
112
+ res = @des.view :by_name
113
+ res["rows"].first["key"].should == "z"
114
+ end
115
+ it "should override them" do
116
+ res = @des.view :by_name, :descending => false
117
+ res["rows"].first["key"].should == "a"
118
+ end
119
+ end
120
+
121
+ describe "a view with multiple keys" do
122
+ before(:all) do
123
+ @db = reset_test_db!
124
+ @des = CouchRest::Design.new
125
+ @des.name = "test"
126
+ @des.view_by :name, :age
127
+ @des.database = @db
128
+ @des.save
129
+ @db.bulk_save([{"name" => "a", "age" => 2},
130
+ {"name" => "a", "age" => 4},{"name" => "z", "age" => 9}])
131
+ end
132
+ it "should work" do
133
+ res = @des.view :by_name_and_age
134
+ res["rows"].first["key"].should == ["a",2]
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,275 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ class Video < CouchRest::Document; end
4
+
5
+ describe CouchRest::Document do
6
+
7
+ before(:all) do
8
+ @couch = CouchRest.new
9
+ @db = @couch.database!(TESTDB)
10
+ end
11
+
12
+ describe "[]=" do
13
+ before(:each) do
14
+ @doc = CouchRest::Document.new
15
+ end
16
+ it "should work" do
17
+ @doc["enamel"].should == nil
18
+ @doc["enamel"] = "Strong"
19
+ @doc["enamel"].should == "Strong"
20
+ end
21
+ it "[]= should convert to string" do
22
+ @doc["enamel"].should == nil
23
+ @doc[:enamel] = "Strong"
24
+ @doc["enamel"].should == "Strong"
25
+ end
26
+ it "should read as a string" do
27
+ @doc[:enamel] = "Strong"
28
+ @doc[:enamel].should == "Strong"
29
+ end
30
+ end
31
+
32
+ describe "default database" do
33
+ before(:each) do
34
+ Video.use_database nil
35
+ end
36
+ it "should be set using use_database on the model" do
37
+ Video.new.database.should be_nil
38
+ Video.use_database @db
39
+ Video.new.database.should == @db
40
+ Video.use_database nil
41
+ end
42
+
43
+ it "should be overwritten by instance" do
44
+ db = @couch.database('test')
45
+ article = Video.new
46
+ article.database.should be_nil
47
+ article.database = db
48
+ article.database.should_not be_nil
49
+ article.database.should == db
50
+ end
51
+ end
52
+
53
+ describe "new" do
54
+ before(:each) do
55
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
56
+ end
57
+ it "should create itself from a Hash" do
58
+ @doc["key"].should == [1,2,3]
59
+ @doc["more"].should == "values"
60
+ end
61
+ it "should not have rev and id" do
62
+ @doc.rev.should be_nil
63
+ @doc.id.should be_nil
64
+ end
65
+
66
+ it "should freak out when saving without a database" do
67
+ lambda{@doc.save}.should raise_error(ArgumentError)
68
+ end
69
+
70
+ end
71
+
72
+ # move to database spec
73
+ describe "saving using a database" do
74
+ before(:all) do
75
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
76
+ @db = reset_test_db!
77
+ @resp = @db.save_doc(@doc)
78
+ end
79
+ it "should apply the database" do
80
+ @doc.database.should == @db
81
+ end
82
+ it "should get id and rev" do
83
+ @doc.id.should == @resp["id"]
84
+ @doc.rev.should == @resp["rev"]
85
+ end
86
+ it "should generate a correct URI" do
87
+ @doc.uri.should == "#{@db.root}/#{@doc.id}"
88
+ URI.parse(@doc.uri).to_s.should == @doc.uri
89
+ end
90
+ it "should generate a correct URI with revision" do
91
+ @doc.uri(true).should == "#{@db.root}/#{@doc.id}?rev=#{@doc.rev}"
92
+ URI.parse(@doc.uri(true)).to_s.should == @doc.uri(true)
93
+ end
94
+ end
95
+
96
+ describe "bulk saving" do
97
+ before :all do
98
+ @db = reset_test_db!
99
+ end
100
+
101
+ it "should use the document bulk save cache" do
102
+ doc = CouchRest::Document.new({"_id" => "bulkdoc", "val" => 3})
103
+ doc.database = @db
104
+ doc.save(true)
105
+ lambda { doc.database.get(doc["_id"]) }.should raise_error(RestClient::ResourceNotFound)
106
+ doc.database.bulk_save
107
+ doc.database.get(doc["_id"])["val"].should == doc["val"]
108
+ end
109
+ end
110
+
111
+ describe "getting from a database" do
112
+ before(:all) do
113
+ @db = reset_test_db!
114
+ @resp = @db.save_doc({
115
+ "key" => "value"
116
+ })
117
+ @doc = @db.get @resp['id']
118
+ end
119
+ it "should return a document" do
120
+ @doc.should be_an_instance_of(CouchRest::Document)
121
+ end
122
+ it "should have a database" do
123
+ @doc.database.should == @db
124
+ end
125
+ it "should be saveable and resavable" do
126
+ @doc["more"] = "keys"
127
+ @doc.save
128
+ @db.get(@resp['id'])["more"].should == "keys"
129
+ @doc["more"] = "these keys"
130
+ @doc.save
131
+ @db.get(@resp['id'])["more"].should == "these keys"
132
+ end
133
+ end
134
+
135
+ describe "destroying a document from a db" do
136
+ before(:all) do
137
+ @db = reset_test_db!
138
+ @resp = @db.save_doc({
139
+ "key" => "value"
140
+ })
141
+ @doc = @db.get @resp['id']
142
+ end
143
+ it "should make it disappear" do
144
+ @doc.destroy
145
+ lambda{@db.get @resp['id']}.should raise_error
146
+ end
147
+ it "should error when there's no db" do
148
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
149
+ lambda{@doc.destroy}.should raise_error(ArgumentError)
150
+ end
151
+ end
152
+
153
+
154
+ describe "destroying a document from a db using bulk save" do
155
+ before(:all) do
156
+ @db = reset_test_db!
157
+ @resp = @db.save_doc({
158
+ "key" => "value"
159
+ })
160
+ @doc = @db.get @resp['id']
161
+ end
162
+ it "should defer actual deletion" do
163
+ @doc.destroy(true)
164
+ @doc['_id'].should == nil
165
+ @doc['_rev'].should == nil
166
+ lambda{@db.get @resp['id']}.should_not raise_error
167
+ @db.bulk_save
168
+ lambda{@db.get @resp['id']}.should raise_error
169
+ end
170
+ end
171
+
172
+ describe "copying a document" do
173
+ before :each do
174
+ @db = reset_test_db!
175
+ @resp = @db.save_doc({'key' => 'value'})
176
+ @docid = 'new-location'
177
+ @doc = @db.get(@resp['id'])
178
+ end
179
+ describe "to a new location" do
180
+ it "should work" do
181
+ @doc.copy @docid
182
+ newdoc = @db.get(@docid)
183
+ newdoc['key'].should == 'value'
184
+ end
185
+ it "should fail without a database" do
186
+ lambda{CouchRest::Document.new({"not"=>"a real doc"}).copy}.should raise_error(ArgumentError)
187
+ end
188
+ end
189
+ describe "to an existing location" do
190
+ before :each do
191
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
192
+ end
193
+ it "should fail without a rev" do
194
+ lambda{@doc.copy @docid}.should raise_error(RestClient::RequestFailed)
195
+ end
196
+ it "should succeed with a rev" do
197
+ @to_be_overwritten = @db.get(@docid)
198
+ @doc.copy "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
199
+ newdoc = @db.get(@docid)
200
+ newdoc['key'].should == 'value'
201
+ end
202
+ it "should succeed given the doc to overwrite" do
203
+ @to_be_overwritten = @db.get(@docid)
204
+ @doc.copy @to_be_overwritten
205
+ newdoc = @db.get(@docid)
206
+ newdoc['key'].should == 'value'
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ describe "dealing with attachments" do
213
+ before do
214
+ @db = reset_test_db!
215
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
216
+ response = @db.save_doc({'key' => 'value'})
217
+ @doc = @db.get(response['id'])
218
+ end
219
+
220
+ def append_attachment(name='test.html', attach=@attach)
221
+ @doc['_attachments'] ||= {}
222
+ @doc['_attachments'][name] = {
223
+ 'type' => 'text/html',
224
+ 'data' => attach
225
+ }
226
+ @doc.save
227
+ @rev = @doc['_rev']
228
+ end
229
+
230
+ describe "PUTing an attachment directly to the doc" do
231
+ before do
232
+ @doc.put_attachment('test.html', @attach)
233
+ end
234
+
235
+ it "is there" do
236
+ @db.fetch_attachment(@doc, 'test.html').should == @attach
237
+ end
238
+
239
+ it "updates the revision" do
240
+ @doc['_rev'].should_not == @rev
241
+ end
242
+
243
+ it "updates attachments" do
244
+ @attach2 = "<html><head><title>My Doc</title></head><body><p>Is Different.</p></body></html>"
245
+ @doc.put_attachment('test.html', @attach2)
246
+ @db.fetch_attachment(@doc, 'test.html').should == @attach2
247
+ end
248
+ end
249
+
250
+ describe "fetching an attachment from a doc directly" do
251
+ before do
252
+ append_attachment
253
+ end
254
+
255
+ it "pulls the attachment" do
256
+ @doc.fetch_attachment('test.html').should == @attach
257
+ end
258
+ end
259
+
260
+ describe "deleting an attachment from a doc directly" do
261
+ before do
262
+ append_attachment
263
+ @doc.delete_attachment('test.html')
264
+ end
265
+
266
+ it "removes it" do
267
+ lambda { @db.fetch_attachment(@doc, 'test.html').should }.should raise_error(RestClient::ResourceNotFound)
268
+ end
269
+
270
+ it "updates the revision" do
271
+ @doc['_rev'].should_not == @rev
272
+ end
273
+ end
274
+
275
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Server do
4
+
5
+ describe "available databases" do
6
+ before(:each) do
7
+ @couch = CouchRest::Server.new
8
+ end
9
+
10
+ after(:each) do
11
+ @couch.available_databases.each do |ref, db|
12
+ db.delete!
13
+ end
14
+ end
15
+
16
+ it "should let you add more databases" do
17
+ @couch.available_databases.should be_empty
18
+ @couch.define_available_database(:default, "cr-server-test-db")
19
+ @couch.available_databases.keys.should include(:default)
20
+ end
21
+
22
+ it "should verify that a database is available" do
23
+ @couch.define_available_database(:default, "cr-server-test-db")
24
+ @couch.available_database?(:default).should be_true
25
+ @couch.available_database?("cr-server-test-db").should be_true
26
+ @couch.available_database?(:matt).should be_false
27
+ end
28
+
29
+ it "should let you set a default database" do
30
+ @couch.default_database = 'cr-server-test-default-db'
31
+ @couch.available_database?(:default).should be_true
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,122 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Pager do
4
+ before(:all) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ @pager = CouchRest::Pager.new(@db)
10
+ end
11
+
12
+ after(:all) do
13
+ begin
14
+ @db.delete!
15
+ rescue RestClient::Request::RequestFailed
16
+ end
17
+ end
18
+
19
+ it "should store the db" do
20
+ @pager.db.should == @db
21
+ end
22
+
23
+ describe "paging all docs" do
24
+ before(:all) do
25
+ @docs = []
26
+ 100.times do |i|
27
+ @docs << ({:number => (i % 10)})
28
+ end
29
+ @db.bulk_save(@docs)
30
+ end
31
+ it "should yield total_docs / limit times" do
32
+ n = 0
33
+ @pager.all_docs(10) do |doc|
34
+ n += 1
35
+ end
36
+ n.should == 10
37
+ end
38
+ it "should yield each docrow group without duplicate docs" do
39
+ docids = {}
40
+ @pager.all_docs(10) do |docrows|
41
+ docrows.each do |row|
42
+ docids[row['id']].should be_nil
43
+ docids[row['id']] = true
44
+ end
45
+ end
46
+ docids.keys.length.should == 100
47
+ end
48
+ it "should yield each docrow group" do
49
+ @pager.all_docs(10) do |docrows|
50
+ doc = @db.get(docrows[0]['id'])
51
+ doc['number'].class.should == Fixnum
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "Pager with a view and docs" do
57
+ before(:all) do
58
+ @docs = []
59
+ 100.times do |i|
60
+ @docs << ({:number => (i % 10)})
61
+ end
62
+ @db.bulk_save(@docs)
63
+ @db.save_doc({
64
+ '_id' => '_design/magic',
65
+ 'views' => {
66
+ 'number' => {
67
+ 'map' => 'function(doc){emit(doc.number,null)}'
68
+ }
69
+ }
70
+ })
71
+ end
72
+
73
+ it "should have docs" do
74
+ @docs.length.should == 100
75
+ @db.documents['rows'].length.should == 101
76
+ end
77
+
78
+ it "should have a view" do
79
+ @db.view('magic/number', :limit => 10)['rows'][0]['key'].should == 0
80
+ end
81
+
82
+ it "should yield once per key" do
83
+ results = {}
84
+ @pager.key_reduce('magic/number', 20) do |k,vs|
85
+ results[k] = vs.length
86
+ end
87
+ results[0].should == 10
88
+ results[3].should == 10
89
+ end
90
+
91
+ it "with a small step size should yield once per key" do
92
+ results = {}
93
+ @pager.key_reduce('magic/number', 7) do |k,vs|
94
+ results[k] = vs.length
95
+ end
96
+ results[0].should == 10
97
+ results[3].should == 10
98
+ results[9].should == 10
99
+ end
100
+ it "with a large step size should yield once per key" do
101
+ results = {}
102
+ @pager.key_reduce('magic/number', 1000) do |k,vs|
103
+ results[k] = vs.length
104
+ end
105
+ results[0].should == 10
106
+ results[3].should == 10
107
+ results[9].should == 10
108
+ end
109
+ it "with a begin and end should only yield in the range (and leave out the lastkey)" do
110
+ results = {}
111
+ @pager.key_reduce('magic/number', 1000, 4, 7) do |k,vs|
112
+ results[k] = vs.length
113
+ end
114
+ results[0].should be_nil
115
+ results[4].should == 10
116
+ results[6].should == 10
117
+ results[7].should be_nil
118
+ results[8].should be_nil
119
+ results[9].should be_nil
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::Streamer do
4
+ before(:all) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ @streamer = CouchRest::Streamer.new(@db)
10
+ @docs = (1..1000).collect{|i| {:integer => i, :string => i.to_s}}
11
+ @db.bulk_save(@docs)
12
+ @db.save_doc({
13
+ "_id" => "_design/first",
14
+ :views => {
15
+ :test => {
16
+ :map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"
17
+ }
18
+ }
19
+ })
20
+ end
21
+
22
+ it "should yield each row in a view" do
23
+ count = 0
24
+ sum = 0
25
+ @streamer.view("_all_docs") do |row|
26
+ count += 1
27
+ end
28
+ count.should == 1001
29
+ end
30
+
31
+ it "should accept several params" do
32
+ count = 0
33
+ @streamer.view("_design/first/_view/test", :include_docs => true, :limit => 5) do |row|
34
+ count += 1
35
+ end
36
+ count.should == 5
37
+ end
38
+
39
+ it "should accept both view formats" do
40
+ count = 0
41
+ @streamer.view("_design/first/_view/test") do |row|
42
+ count += 1
43
+ end
44
+ count.should == 2000
45
+ count = 0
46
+ @streamer.view("first/test") do |row|
47
+ count += 1
48
+ end
49
+ count.should == 2000
50
+ end
51
+
52
+ end