samlown-couchrest 0.35

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 (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