couchrest 0.12.4 → 0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/README.md +33 -8
  2. data/Rakefile +11 -2
  3. data/examples/model/example.rb +19 -13
  4. data/lib/couchrest.rb +70 -11
  5. data/lib/couchrest/core/database.rb +121 -62
  6. data/lib/couchrest/core/design.rb +7 -17
  7. data/lib/couchrest/core/document.rb +42 -30
  8. data/lib/couchrest/core/response.rb +16 -0
  9. data/lib/couchrest/core/server.rb +47 -10
  10. data/lib/couchrest/helper/upgrade.rb +51 -0
  11. data/lib/couchrest/mixins.rb +4 -0
  12. data/lib/couchrest/mixins/attachments.rb +31 -0
  13. data/lib/couchrest/mixins/callbacks.rb +483 -0
  14. data/lib/couchrest/mixins/class_proxy.rb +108 -0
  15. data/lib/couchrest/mixins/design_doc.rb +90 -0
  16. data/lib/couchrest/mixins/document_queries.rb +44 -0
  17. data/lib/couchrest/mixins/extended_attachments.rb +68 -0
  18. data/lib/couchrest/mixins/extended_document_mixins.rb +7 -0
  19. data/lib/couchrest/mixins/properties.rb +129 -0
  20. data/lib/couchrest/mixins/validation.rb +242 -0
  21. data/lib/couchrest/mixins/views.rb +169 -0
  22. data/lib/couchrest/monkeypatches.rb +81 -6
  23. data/lib/couchrest/more/casted_model.rb +28 -0
  24. data/lib/couchrest/more/extended_document.rb +215 -0
  25. data/lib/couchrest/more/property.rb +40 -0
  26. data/lib/couchrest/support/blank.rb +42 -0
  27. data/lib/couchrest/support/class.rb +176 -0
  28. data/lib/couchrest/validation/auto_validate.rb +163 -0
  29. data/lib/couchrest/validation/contextual_validators.rb +78 -0
  30. data/lib/couchrest/validation/validation_errors.rb +118 -0
  31. data/lib/couchrest/validation/validators/absent_field_validator.rb +74 -0
  32. data/lib/couchrest/validation/validators/confirmation_validator.rb +99 -0
  33. data/lib/couchrest/validation/validators/format_validator.rb +117 -0
  34. data/lib/couchrest/validation/validators/formats/email.rb +66 -0
  35. data/lib/couchrest/validation/validators/formats/url.rb +43 -0
  36. data/lib/couchrest/validation/validators/generic_validator.rb +120 -0
  37. data/lib/couchrest/validation/validators/length_validator.rb +134 -0
  38. data/lib/couchrest/validation/validators/method_validator.rb +89 -0
  39. data/lib/couchrest/validation/validators/numeric_validator.rb +104 -0
  40. data/lib/couchrest/validation/validators/required_field_validator.rb +109 -0
  41. data/spec/couchrest/core/database_spec.rb +189 -124
  42. data/spec/couchrest/core/design_spec.rb +13 -6
  43. data/spec/couchrest/core/document_spec.rb +231 -177
  44. data/spec/couchrest/core/server_spec.rb +35 -0
  45. data/spec/couchrest/helpers/pager_spec.rb +1 -1
  46. data/spec/couchrest/more/casted_extended_doc_spec.rb +40 -0
  47. data/spec/couchrest/more/casted_model_spec.rb +98 -0
  48. data/spec/couchrest/more/extended_doc_attachment_spec.rb +130 -0
  49. data/spec/couchrest/more/extended_doc_spec.rb +509 -0
  50. data/spec/couchrest/more/extended_doc_subclass_spec.rb +98 -0
  51. data/spec/couchrest/more/extended_doc_view_spec.rb +355 -0
  52. data/spec/couchrest/more/property_spec.rb +136 -0
  53. data/spec/fixtures/more/article.rb +34 -0
  54. data/spec/fixtures/more/card.rb +20 -0
  55. data/spec/fixtures/more/course.rb +14 -0
  56. data/spec/fixtures/more/event.rb +6 -0
  57. data/spec/fixtures/more/invoice.rb +17 -0
  58. data/spec/fixtures/more/person.rb +8 -0
  59. data/spec/fixtures/more/question.rb +6 -0
  60. data/spec/fixtures/more/service.rb +12 -0
  61. data/spec/spec_helper.rb +13 -7
  62. metadata +58 -4
  63. data/lib/couchrest/core/model.rb +0 -613
  64. data/spec/couchrest/core/model_spec.rb +0 -855
@@ -14,7 +14,7 @@ describe CouchRest::Design do
14
14
  describe "with an unsaved view" do
15
15
  before(:each) do
16
16
  @des = CouchRest::Design.new
17
- method = @des.view_by :name
17
+ @des.view_by :name
18
18
  end
19
19
  it "should accept a name" do
20
20
  @des.name = "mytest"
@@ -31,7 +31,7 @@ describe CouchRest::Design do
31
31
  describe "saving" do
32
32
  before(:each) do
33
33
  @des = CouchRest::Design.new
34
- method = @des.view_by :name
34
+ @des.view_by :name
35
35
  @des.database = reset_test_db!
36
36
  end
37
37
  it "should fail without a name" do
@@ -49,7 +49,7 @@ describe CouchRest::Design do
49
49
  @db.bulk_save([{"name" => "x"},{"name" => "y"}])
50
50
  @des = CouchRest::Design.new
51
51
  @des.database = @db
52
- method = @des.view_by :name
52
+ @des.view_by :name
53
53
  end
54
54
  it "should by queryable when it's saved" do
55
55
  @des.name = "mydesign"
@@ -57,12 +57,19 @@ describe CouchRest::Design do
57
57
  res = @des.view :by_name
58
58
  res["rows"][0]["key"].should == "x"
59
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
60
67
  end
61
68
 
62
69
  describe "from a saved document" do
63
70
  before(:each) do
64
71
  @db = reset_test_db!
65
- @db.save({
72
+ @db.save_doc({
66
73
  "_id" => "_design/test",
67
74
  "views" => {
68
75
  "by_name" => {
@@ -92,7 +99,7 @@ describe CouchRest::Design do
92
99
  @db = reset_test_db!
93
100
  @des = CouchRest::Design.new
94
101
  @des.name = "test"
95
- method = @des.view_by :name, :descending => true
102
+ @des.view_by :name, :descending => true
96
103
  @des.database = @db
97
104
  @des.save
98
105
  @db.bulk_save([{"name" => "a"},{"name" => "z"}])
@@ -116,7 +123,7 @@ describe CouchRest::Design do
116
123
  @db = reset_test_db!
117
124
  @des = CouchRest::Design.new
118
125
  @des.name = "test"
119
- method = @des.view_by :name, :age
126
+ @des.view_by :name, :age
120
127
  @des.database = @db
121
128
  @des.save
122
129
  @db.bulk_save([{"name" => "a", "age" => 2},
@@ -1,213 +1,267 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
- describe CouchRest::Document, "[]=" do
4
- before(:each) do
5
- @doc = CouchRest::Document.new
6
- end
7
- it "should work" do
8
- @doc["enamel"].should == nil
9
- @doc["enamel"] = "Strong"
10
- @doc["enamel"].should == "Strong"
11
- end
12
- it "[]= should convert to string" do
13
- @doc["enamel"].should == nil
14
- @doc[:enamel] = "Strong"
15
- @doc["enamel"].should == "Strong"
16
- end
17
- it "should read as a string" do
18
- @doc[:enamel] = "Strong"
19
- @doc[:enamel].should == "Strong"
20
- end
21
- end
3
+ class Video < CouchRest::Document; end
22
4
 
23
- describe CouchRest::Document, "new" do
24
- before(:each) do
25
- @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
26
- end
27
- it "should create itself from a Hash" do
28
- @doc["key"].should == [1,2,3]
29
- @doc["more"].should == "values"
30
- end
31
- it "should not have rev and id" do
32
- @doc.rev.should be_nil
33
- @doc.id.should be_nil
34
- end
35
- it "should freak out when saving without a database" do
36
- lambda{@doc.save}.should raise_error(ArgumentError)
37
- end
38
- end
39
-
40
- # move to database spec
41
- describe CouchRest::Document, "saving using a database" do
5
+ describe CouchRest::Document do
6
+
42
7
  before(:all) do
43
- @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
44
- @db = reset_test_db!
45
- @resp = @db.save(@doc)
46
- end
47
- it "should apply the database" do
48
- @doc.database.should == @db
49
- end
50
- it "should get id and rev" do
51
- @doc.id.should == @resp["id"]
52
- @doc.rev.should == @resp["rev"]
8
+ @couch = CouchRest.new
9
+ @db = @couch.database!(TESTDB)
53
10
  end
54
- end
55
11
 
56
- describe CouchRest::Document, "bulk saving" do
57
- before :all do
58
- @db = reset_test_db!
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
59
30
  end
60
31
 
61
- it "should use the document bulk save cache" do
62
- doc = CouchRest::Document.new({"_id" => "bulkdoc", "val" => 3})
63
- doc.database = @db
64
- doc.save(true)
65
- lambda { doc.database.get(doc["_id"]) }.should raise_error(RestClient::ResourceNotFound)
66
- doc.database.bulk_save
67
- doc.database.get(doc["_id"])["val"].should == doc["val"]
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
68
51
  end
69
- end
70
52
 
71
- describe "getting from a database" do
72
- before(:all) do
73
- @db = reset_test_db!
74
- @resp = @db.save({
75
- "key" => "value"
76
- })
77
- @doc = @db.get @resp['id']
78
- end
79
- it "should return a document" do
80
- @doc.should be_an_instance_of(CouchRest::Document)
81
- end
82
- it "should have a database" do
83
- @doc.database.should == @db
84
- end
85
- it "should be saveable and resavable" do
86
- @doc["more"] = "keys"
87
- @doc.save
88
- @db.get(@resp['id'])["more"].should == "keys"
89
- @doc["more"] = "these keys"
90
- @doc.save
91
- @db.get(@resp['id'])["more"].should == "these keys"
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
+
92
70
  end
93
- end
94
71
 
95
- describe "destroying a document from a db" do
96
- before(:all) do
97
- @db = reset_test_db!
98
- @resp = @db.save({
99
- "key" => "value"
100
- })
101
- @doc = @db.get @resp['id']
102
- end
103
- it "should make it disappear" do
104
- @doc.destroy
105
- lambda{@db.get @resp['id']}.should raise_error
106
- end
107
- it "should error when there's no db" do
108
- @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
109
- lambda{@doc.destroy}.should raise_error(ArgumentError)
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
110
86
  end
111
- end
112
87
 
88
+ describe "bulk saving" do
89
+ before :all do
90
+ @db = reset_test_db!
91
+ end
113
92
 
114
- describe "destroying a document from a db using bulk save" do
115
- before(:all) do
116
- @db = reset_test_db!
117
- @resp = @db.save({
118
- "key" => "value"
119
- })
120
- @doc = @db.get @resp['id']
93
+ it "should use the document bulk save cache" do
94
+ doc = CouchRest::Document.new({"_id" => "bulkdoc", "val" => 3})
95
+ doc.database = @db
96
+ doc.save(true)
97
+ lambda { doc.database.get(doc["_id"]) }.should raise_error(RestClient::ResourceNotFound)
98
+ doc.database.bulk_save
99
+ doc.database.get(doc["_id"])["val"].should == doc["val"]
100
+ end
121
101
  end
122
- it "should defer actual deletion" do
123
- @doc.destroy(true)
124
- @doc['_id'].should == nil
125
- @doc['_rev'].should == nil
126
- lambda{@db.get @resp['id']}.should_not raise_error
127
- @db.bulk_save
128
- lambda{@db.get @resp['id']}.should raise_error
102
+
103
+ describe "getting from a database" do
104
+ before(:all) do
105
+ @db = reset_test_db!
106
+ @resp = @db.save_doc({
107
+ "key" => "value"
108
+ })
109
+ @doc = @db.get @resp['id']
110
+ end
111
+ it "should return a document" do
112
+ @doc.should be_an_instance_of(CouchRest::Document)
113
+ end
114
+ it "should have a database" do
115
+ @doc.database.should == @db
116
+ end
117
+ it "should be saveable and resavable" do
118
+ @doc["more"] = "keys"
119
+ @doc.save
120
+ @db.get(@resp['id'])["more"].should == "keys"
121
+ @doc["more"] = "these keys"
122
+ @doc.save
123
+ @db.get(@resp['id'])["more"].should == "these keys"
124
+ end
129
125
  end
130
- end
131
126
 
132
- describe "copying a document" do
133
- before :each do
134
- @db = reset_test_db!
135
- @resp = @db.save({'key' => 'value'})
136
- @docid = 'new-location'
137
- @doc = @db.get(@resp['id'])
127
+ describe "destroying a document from a db" do
128
+ before(:all) do
129
+ @db = reset_test_db!
130
+ @resp = @db.save_doc({
131
+ "key" => "value"
132
+ })
133
+ @doc = @db.get @resp['id']
134
+ end
135
+ it "should make it disappear" do
136
+ @doc.destroy
137
+ lambda{@db.get @resp['id']}.should raise_error
138
+ end
139
+ it "should error when there's no db" do
140
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
141
+ lambda{@doc.destroy}.should raise_error(ArgumentError)
142
+ end
138
143
  end
139
- describe "to a new location" do
140
- it "should work" do
141
- @doc.copy @docid
142
- newdoc = @db.get(@docid)
143
- newdoc['key'].should == 'value'
144
+
145
+
146
+ describe "destroying a document from a db using bulk save" do
147
+ before(:all) do
148
+ @db = reset_test_db!
149
+ @resp = @db.save_doc({
150
+ "key" => "value"
151
+ })
152
+ @doc = @db.get @resp['id']
144
153
  end
145
- it "should fail without a database" do
146
- lambda{CouchRest::Document.new({"not"=>"a real doc"}).copy}.should raise_error(ArgumentError)
154
+ it "should defer actual deletion" do
155
+ @doc.destroy(true)
156
+ @doc['_id'].should == nil
157
+ @doc['_rev'].should == nil
158
+ lambda{@db.get @resp['id']}.should_not raise_error
159
+ @db.bulk_save
160
+ lambda{@db.get @resp['id']}.should raise_error
147
161
  end
148
162
  end
149
- describe "to an existing location" do
163
+
164
+ describe "copying a document" do
150
165
  before :each do
151
- @db.save({'_id' => @docid, 'will-exist' => 'here'})
166
+ @db = reset_test_db!
167
+ @resp = @db.save_doc({'key' => 'value'})
168
+ @docid = 'new-location'
169
+ @doc = @db.get(@resp['id'])
152
170
  end
153
- it "should fail without a rev" do
154
- lambda{@doc.copy @docid}.should raise_error(RestClient::RequestFailed)
171
+ describe "to a new location" do
172
+ it "should work" do
173
+ @doc.copy @docid
174
+ newdoc = @db.get(@docid)
175
+ newdoc['key'].should == 'value'
176
+ end
177
+ it "should fail without a database" do
178
+ lambda{CouchRest::Document.new({"not"=>"a real doc"}).copy}.should raise_error(ArgumentError)
179
+ end
155
180
  end
156
- it "should succeed with a rev" do
157
- @to_be_overwritten = @db.get(@docid)
158
- @doc.copy "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
159
- newdoc = @db.get(@docid)
160
- newdoc['key'].should == 'value'
161
- end
162
- it "should succeed given the doc to overwrite" do
163
- @to_be_overwritten = @db.get(@docid)
164
- @doc.copy @to_be_overwritten
165
- newdoc = @db.get(@docid)
166
- newdoc['key'].should == 'value'
181
+ describe "to an existing location" do
182
+ before :each do
183
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
184
+ end
185
+ it "should fail without a rev" do
186
+ lambda{@doc.copy @docid}.should raise_error(RestClient::RequestFailed)
187
+ end
188
+ it "should succeed with a rev" do
189
+ @to_be_overwritten = @db.get(@docid)
190
+ @doc.copy "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
191
+ newdoc = @db.get(@docid)
192
+ newdoc['key'].should == 'value'
193
+ end
194
+ it "should succeed given the doc to overwrite" do
195
+ @to_be_overwritten = @db.get(@docid)
196
+ @doc.copy @to_be_overwritten
197
+ newdoc = @db.get(@docid)
198
+ newdoc['key'].should == 'value'
199
+ end
167
200
  end
168
201
  end
169
202
  end
170
203
 
171
- describe "MOVE existing document" do
172
- before :each do
204
+ describe "dealing with attachments" do
205
+ before do
173
206
  @db = reset_test_db!
174
- @resp = @db.save({'key' => 'value'})
175
- @docid = 'new-location'
176
- @doc = @db.get(@resp['id'])
207
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
208
+ response = @db.save_doc({'key' => 'value'})
209
+ @doc = @db.get(response['id'])
177
210
  end
178
- describe "to a new location" do
179
- it "should work" do
180
- @doc.move @docid
181
- newdoc = @db.get(@docid)
182
- newdoc['key'].should == 'value'
183
- lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
211
+
212
+ def append_attachment(name='test.html', attach=@attach)
213
+ @doc['_attachments'] ||= {}
214
+ @doc['_attachments'][name] = {
215
+ 'type' => 'text/html',
216
+ 'data' => attach
217
+ }
218
+ @doc.save
219
+ @rev = @doc['_rev']
220
+ end
221
+
222
+ describe "PUTing an attachment directly to the doc" do
223
+ before do
224
+ @doc.put_attachment('test.html', @attach)
184
225
  end
185
- it "should fail without a database" do
186
- lambda{CouchRest::Document.new({"not"=>"a real doc"}).move}.should raise_error(ArgumentError)
187
- lambda{CouchRest::Document.new({"_id"=>"not a real doc"}).move}.should raise_error(ArgumentError)
226
+
227
+ it "is there" do
228
+ @db.fetch_attachment(@doc, 'test.html').should == @attach
229
+ end
230
+
231
+ it "updates the revision" do
232
+ @doc['_rev'].should_not == @rev
233
+ end
234
+
235
+ it "updates attachments" do
236
+ @attach2 = "<html><head><title>My Doc</title></head><body><p>Is Different.</p></body></html>"
237
+ @doc.put_attachment('test.html', @attach2)
238
+ @db.fetch_attachment(@doc, 'test.html').should == @attach2
188
239
  end
189
240
  end
190
- describe "to an existing location" do
191
- before :each do
192
- @db.save({'_id' => @docid, 'will-exist' => 'here'})
193
- end
194
- it "should fail without a rev" do
195
- lambda{@doc.move @docid}.should raise_error(RestClient::RequestFailed)
196
- lambda{@db.get(@resp['id'])}.should_not raise_error
197
- end
198
- it "should succeed with a rev" do
199
- @to_be_overwritten = @db.get(@docid)
200
- @doc.move "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
201
- newdoc = @db.get(@docid)
202
- newdoc['key'].should == 'value'
203
- lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
204
- end
205
- it "should succeed given the doc to overwrite" do
206
- @to_be_overwritten = @db.get(@docid)
207
- @doc.move @to_be_overwritten
208
- newdoc = @db.get(@docid)
209
- newdoc['key'].should == 'value'
210
- lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
241
+
242
+ describe "fetching an attachment from a doc directly" do
243
+ before do
244
+ append_attachment
245
+ end
246
+
247
+ it "pulls the attachment" do
248
+ @doc.fetch_attachment('test.html').should == @attach
211
249
  end
212
250
  end
213
- end
251
+
252
+ describe "deleting an attachment from a doc directly" do
253
+ before do
254
+ append_attachment
255
+ @doc.delete_attachment('test.html')
256
+ end
257
+
258
+ it "removes it" do
259
+ lambda { @db.fetch_attachment(@doc, 'test.html').should }.should raise_error(RestClient::ResourceNotFound)
260
+ end
261
+
262
+ it "updates the revision" do
263
+ @doc['_rev'].should_not == @rev
264
+ end
265
+ end
266
+
267
+ end