jchris-couchrest 0.9.12 → 0.12.2
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.
- data/{README.rdoc → README.md} +10 -8
- data/Rakefile +60 -39
- data/THANKS.md +18 -0
- data/examples/word_count/markov +1 -1
- data/examples/word_count/views/word_count/count-reduce.js +2 -2
- data/examples/word_count/word_count.rb +2 -2
- data/examples/word_count/word_count_query.rb +2 -2
- data/lib/couchrest/commands/push.rb +8 -4
- data/lib/couchrest/core/database.rb +95 -14
- data/lib/couchrest/core/design.rb +89 -0
- data/lib/couchrest/core/document.rb +63 -0
- data/lib/couchrest/core/model.rb +203 -120
- data/lib/couchrest/core/server.rb +1 -1
- data/lib/couchrest/core/view.rb +4 -0
- data/lib/couchrest/helper/pager.rb +10 -10
- data/lib/couchrest/monkeypatches.rb +1 -1
- data/lib/couchrest.rb +20 -2
- data/spec/couchrest/core/couchrest_spec.rb +33 -23
- data/spec/couchrest/core/database_spec.rb +163 -8
- data/spec/couchrest/core/design_spec.rb +131 -0
- data/spec/couchrest/core/document_spec.rb +130 -0
- data/spec/couchrest/core/model_spec.rb +319 -35
- data/spec/couchrest/helpers/pager_spec.rb +2 -2
- data/spec/fixtures/attachments/README +3 -0
- data/spec/spec_helper.rb +17 -3
- data/utils/remap.rb +2 -2
- data/utils/subset.rb +2 -2
- metadata +24 -33
- data/THANKS +0 -15
- data/bin/couchapp +0 -55
- data/bin/couchview +0 -48
- data/lib/couchrest/helper/file_manager.rb +0 -285
- data/lib/couchrest/helper/templates/example-map.js +0 -8
- data/lib/couchrest/helper/templates/example-reduce.js +0 -10
- data/lib/couchrest/helper/templates/index.html +0 -26
- data/spec/couchapp_spec.rb +0 -82
- data/spec/couchrest/helpers/file_manager_spec.rb +0 -170
@@ -3,7 +3,17 @@ require File.dirname(__FILE__) + '/../../spec_helper'
|
|
3
3
|
class Basic < CouchRest::Model
|
4
4
|
end
|
5
5
|
|
6
|
-
class
|
6
|
+
class BasicWithValidation < CouchRest::Model
|
7
|
+
|
8
|
+
before :save, :validate
|
9
|
+
key_accessor :name
|
10
|
+
|
11
|
+
def validate
|
12
|
+
throw(:halt, false) unless name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class WithTemplateAndUniqueID < CouchRest::Model
|
7
17
|
unique_id do |model|
|
8
18
|
model['important-field']
|
9
19
|
end
|
@@ -12,10 +22,12 @@ class WithTemplate < CouchRest::Model
|
|
12
22
|
'more-template' => [1,2,3]
|
13
23
|
})
|
14
24
|
key_accessor :preset
|
25
|
+
key_accessor :has_no_default
|
15
26
|
end
|
16
27
|
|
17
28
|
class Question < CouchRest::Model
|
18
29
|
key_accessor :q, :a
|
30
|
+
couchrest_type = 'Question'
|
19
31
|
end
|
20
32
|
|
21
33
|
class Person < CouchRest::Model
|
@@ -29,12 +41,13 @@ class Course < CouchRest::Model
|
|
29
41
|
key_accessor :title
|
30
42
|
cast :questions, :as => ['Question']
|
31
43
|
cast :professor, :as => 'Person'
|
44
|
+
cast :final_test_at, :as => 'Time'
|
32
45
|
view_by :title
|
33
46
|
view_by :dept, :ducktype => true
|
34
47
|
end
|
35
48
|
|
36
49
|
class Article < CouchRest::Model
|
37
|
-
use_database CouchRest.database!('http://
|
50
|
+
use_database CouchRest.database!('http://127.0.0.1:5984/couchrest-model-test')
|
38
51
|
unique_id :slug
|
39
52
|
|
40
53
|
view_by :date, :descending => true
|
@@ -60,12 +73,42 @@ class Article < CouchRest::Model
|
|
60
73
|
|
61
74
|
timestamps!
|
62
75
|
|
63
|
-
before(:
|
76
|
+
before(:save, :generate_slug_from_title)
|
64
77
|
def generate_slug_from_title
|
65
|
-
self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'')
|
78
|
+
self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new_document?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Player < CouchRest::Model
|
83
|
+
unique_id :email
|
84
|
+
|
85
|
+
key_accessor :email, :name, :str, :coord, :int, :con, :spirit, :level, :xp, :points, :coins, :date, :items, :loc
|
86
|
+
|
87
|
+
view_by :name, :descending => true
|
88
|
+
view_by :loc
|
89
|
+
|
90
|
+
timestamps!
|
91
|
+
end
|
92
|
+
|
93
|
+
class Event < CouchRest::Model
|
94
|
+
key_accessor :subject, :occurs_at
|
95
|
+
|
96
|
+
cast :occurs_at, :as => 'Time', :send => 'parse'
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "save bug" do
|
100
|
+
before(:each) do
|
101
|
+
CouchRest::Model.default_database = reset_test_db!
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should fix" do
|
105
|
+
@p = Player.new
|
106
|
+
@p.email = 'insane@fakestreet.com'
|
107
|
+
@p.save
|
66
108
|
end
|
67
109
|
end
|
68
110
|
|
111
|
+
|
69
112
|
describe CouchRest::Model do
|
70
113
|
before(:all) do
|
71
114
|
@cr = CouchRest.new(COUCHHOST)
|
@@ -74,8 +117,8 @@ describe CouchRest::Model do
|
|
74
117
|
@db = @cr.create_db(TESTDB) rescue nil
|
75
118
|
@adb = @cr.database('couchrest-model-test')
|
76
119
|
@adb.delete! rescue nil
|
77
|
-
CouchRest.database!('http://
|
78
|
-
CouchRest::Model.default_database = CouchRest.database!('http://
|
120
|
+
CouchRest.database!('http://127.0.0.1:5984/couchrest-model-test')
|
121
|
+
CouchRest::Model.default_database = CouchRest.database!('http://127.0.0.1:5984/couchrest-test')
|
79
122
|
end
|
80
123
|
|
81
124
|
it "should use the default database" do
|
@@ -134,7 +177,7 @@ describe CouchRest::Model do
|
|
134
177
|
end
|
135
178
|
end
|
136
179
|
|
137
|
-
describe "update attributes" do
|
180
|
+
describe "update attributes without saving" do
|
138
181
|
before(:each) do
|
139
182
|
a = Article.get "big-bad-danger" rescue nil
|
140
183
|
a.destroy if a
|
@@ -160,22 +203,51 @@ describe CouchRest::Model do
|
|
160
203
|
@art['title'].should == "big bad danger"
|
161
204
|
end
|
162
205
|
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "update attributes" do
|
209
|
+
before(:each) do
|
210
|
+
a = Article.get "big-bad-danger" rescue nil
|
211
|
+
a.destroy if a
|
212
|
+
@art = Article.new(:title => "big bad danger")
|
213
|
+
@art.save
|
214
|
+
end
|
163
215
|
it "should save" do
|
164
216
|
@art['title'].should == "big bad danger"
|
165
217
|
@art.update_attributes('date' => Time.now, :title => "super danger")
|
166
218
|
loaded = Article.get @art.id
|
167
219
|
loaded['title'].should == "super danger"
|
168
220
|
end
|
169
|
-
|
170
221
|
end
|
171
222
|
|
172
223
|
describe "a model with template values" do
|
173
224
|
before(:all) do
|
174
|
-
@tmpl =
|
225
|
+
@tmpl = WithTemplateAndUniqueID.new
|
226
|
+
@tmpl2 = WithTemplateAndUniqueID.new(:preset => 'not_value', 'important-field' => '1')
|
175
227
|
end
|
176
228
|
it "should have fields set when new" do
|
177
229
|
@tmpl.preset.should == 'value'
|
178
230
|
end
|
231
|
+
it "shouldn't override explicitly set values" do
|
232
|
+
@tmpl2.preset.should == 'not_value'
|
233
|
+
end
|
234
|
+
it "shouldn't override existing documents" do
|
235
|
+
@tmpl2.save
|
236
|
+
tmpl2_reloaded = WithTemplateAndUniqueID.get(@tmpl2.id)
|
237
|
+
@tmpl2.preset.should == 'not_value'
|
238
|
+
tmpl2_reloaded.preset.should == 'not_value'
|
239
|
+
end
|
240
|
+
it "shouldn't fill in existing documents" do
|
241
|
+
@tmpl2.save
|
242
|
+
# If user adds a new default value, shouldn't be retroactively applied to
|
243
|
+
# documents upon fetching
|
244
|
+
WithTemplateAndUniqueID.set_default({:has_no_default => 'giraffe'})
|
245
|
+
|
246
|
+
tmpl2_reloaded = WithTemplateAndUniqueID.get(@tmpl2.id)
|
247
|
+
@tmpl2.has_no_default.should be_nil
|
248
|
+
tmpl2_reloaded.has_no_default.should be_nil
|
249
|
+
WithTemplateAndUniqueID.new.has_no_default.should == 'giraffe'
|
250
|
+
end
|
179
251
|
end
|
180
252
|
|
181
253
|
describe "getting a model" do
|
@@ -213,32 +285,56 @@ describe CouchRest::Model do
|
|
213
285
|
@course["questions"][0].a[0].should == "beast"
|
214
286
|
end
|
215
287
|
end
|
216
|
-
|
288
|
+
|
217
289
|
describe "finding all instances of a model" do
|
218
290
|
before(:all) do
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
291
|
+
WithTemplateAndUniqueID.new('important-field' => '1').save
|
292
|
+
WithTemplateAndUniqueID.new('important-field' => '2').save
|
293
|
+
WithTemplateAndUniqueID.new('important-field' => '3').save
|
294
|
+
WithTemplateAndUniqueID.new('important-field' => '4').save
|
223
295
|
end
|
224
296
|
it "should make the design doc" do
|
225
|
-
|
226
|
-
d =
|
227
|
-
d['views']['all']['map'].should include('
|
297
|
+
WithTemplateAndUniqueID.all
|
298
|
+
d = WithTemplateAndUniqueID.design_doc
|
299
|
+
d['views']['all']['map'].should include('WithTemplateAndUniqueID')
|
228
300
|
end
|
229
301
|
it "should find all" do
|
230
|
-
rs =
|
302
|
+
rs = WithTemplateAndUniqueID.all
|
231
303
|
rs.length.should == 4
|
232
304
|
end
|
233
305
|
end
|
234
306
|
|
307
|
+
describe "finding the first instance of a model" do
|
308
|
+
before(:each) do
|
309
|
+
@db = reset_test_db!
|
310
|
+
WithTemplateAndUniqueID.new('important-field' => '1').save
|
311
|
+
WithTemplateAndUniqueID.new('important-field' => '2').save
|
312
|
+
WithTemplateAndUniqueID.new('important-field' => '3').save
|
313
|
+
WithTemplateAndUniqueID.new('important-field' => '4').save
|
314
|
+
end
|
315
|
+
it "should make the design doc" do
|
316
|
+
WithTemplateAndUniqueID.all
|
317
|
+
d = WithTemplateAndUniqueID.design_doc
|
318
|
+
d['views']['all']['map'].should include('WithTemplateAndUniqueID')
|
319
|
+
end
|
320
|
+
it "should find first" do
|
321
|
+
rs = WithTemplateAndUniqueID.first
|
322
|
+
rs['important-field'].should == "1"
|
323
|
+
end
|
324
|
+
it "should return nil if no instances are found" do
|
325
|
+
WithTemplateAndUniqueID.all.each {|obj| obj.destroy }
|
326
|
+
WithTemplateAndUniqueID.first.should be_nil
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
235
330
|
describe "getting a model with a subobject field" do
|
236
331
|
before(:all) do
|
237
332
|
course_doc = {
|
238
333
|
"title" => "Metaphysics 410",
|
239
334
|
"professor" => {
|
240
335
|
"name" => ["Mark", "Hinchliff"]
|
241
|
-
}
|
336
|
+
},
|
337
|
+
"final_test_at" => "2008/12/19 13:00:00 +0800"
|
242
338
|
}
|
243
339
|
r = Course.database.save course_doc
|
244
340
|
@course = Course.get r['id']
|
@@ -249,6 +345,21 @@ describe CouchRest::Model do
|
|
249
345
|
it "should instantiate the professor as a person" do
|
250
346
|
@course['professor'].last_name.should == "Hinchliff"
|
251
347
|
end
|
348
|
+
it "should instantiate the final_test_at as a Time" do
|
349
|
+
@course['final_test_at'].should == Time.parse("2008/12/19 13:00:00 +0800")
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
describe "cast keys to any type" do
|
354
|
+
before(:all) do
|
355
|
+
event_doc = { :subject => "Some event", :occurs_at => Time.now }
|
356
|
+
e = Event.database.save event_doc
|
357
|
+
|
358
|
+
@event = Event.get e['id']
|
359
|
+
end
|
360
|
+
it "should cast created_at to Time" do
|
361
|
+
@event['occurs_at'].should be_an_instance_of(Time)
|
362
|
+
end
|
252
363
|
end
|
253
364
|
|
254
365
|
describe "saving a model" do
|
@@ -277,6 +388,21 @@ describe CouchRest::Model do
|
|
277
388
|
@obj['couchrest-type'].should == 'Basic'
|
278
389
|
end
|
279
390
|
end
|
391
|
+
|
392
|
+
describe "saving a model with validation hooks added as extlib" do
|
393
|
+
before(:all) do
|
394
|
+
@obj = BasicWithValidation.new
|
395
|
+
end
|
396
|
+
|
397
|
+
it "save should return false is the model doesn't save as expected" do
|
398
|
+
@obj.save.should be_false
|
399
|
+
end
|
400
|
+
|
401
|
+
it "save! should raise and exception if the model doesn't save" do
|
402
|
+
lambda{ @obj.save!}.should raise_error("#{@obj.inspect} failed to save")
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
280
406
|
|
281
407
|
describe "saving a model with a unique_id configured" do
|
282
408
|
before(:each) do
|
@@ -285,6 +411,11 @@ describe CouchRest::Model do
|
|
285
411
|
Article.database.delete(@old) if @old
|
286
412
|
end
|
287
413
|
|
414
|
+
it "should be a new document" do
|
415
|
+
@art.should be_a_new_document
|
416
|
+
@art.title.should be_nil
|
417
|
+
end
|
418
|
+
|
288
419
|
it "should require the title" do
|
289
420
|
lambda{@art.save}.should raise_error
|
290
421
|
@art.title = 'This is the title'
|
@@ -321,8 +452,8 @@ describe CouchRest::Model do
|
|
321
452
|
|
322
453
|
describe "saving a model with a unique_id lambda" do
|
323
454
|
before(:each) do
|
324
|
-
@templated =
|
325
|
-
@old =
|
455
|
+
@templated = WithTemplateAndUniqueID.new
|
456
|
+
@old = WithTemplateAndUniqueID.get('very-important') rescue nil
|
326
457
|
@old.destroy if @old
|
327
458
|
end
|
328
459
|
|
@@ -335,7 +466,7 @@ describe CouchRest::Model do
|
|
335
466
|
it "should save with the id" do
|
336
467
|
@templated['important-field'] = 'very-important'
|
337
468
|
@templated.save.should == true
|
338
|
-
t =
|
469
|
+
t = WithTemplateAndUniqueID.get('very-important')
|
339
470
|
t.should == @templated
|
340
471
|
end
|
341
472
|
|
@@ -344,14 +475,14 @@ describe CouchRest::Model do
|
|
344
475
|
@templated.save.should == true
|
345
476
|
@templated['important-field'] = 'not-important'
|
346
477
|
@templated.save.should == true
|
347
|
-
t =
|
478
|
+
t = WithTemplateAndUniqueID.get('very-important')
|
348
479
|
t.should == @templated
|
349
480
|
end
|
350
481
|
|
351
482
|
it "should raise an error when the id is taken" do
|
352
483
|
@templated['important-field'] = 'very-important'
|
353
484
|
@templated.save.should == true
|
354
|
-
lambda{
|
485
|
+
lambda{WithTemplateAndUniqueID.new('important-field' => 'very-important').save}.should raise_error
|
355
486
|
end
|
356
487
|
|
357
488
|
it "should set the id" do
|
@@ -390,10 +521,14 @@ describe CouchRest::Model do
|
|
390
521
|
written_at += 24 * 3600
|
391
522
|
end
|
392
523
|
end
|
524
|
+
|
525
|
+
it "should have a design doc" do
|
526
|
+
Article.design_doc["views"]["by_date"].should_not be_nil
|
527
|
+
end
|
393
528
|
|
394
|
-
it "should
|
395
|
-
Article.by_date rescue nil
|
396
|
-
doc = Article.design_doc
|
529
|
+
it "should save the design doc" do
|
530
|
+
Article.by_date #rescue nil
|
531
|
+
doc = Article.database.get Article.design_doc.id
|
397
532
|
doc['views']['by_date'].should_not be_nil
|
398
533
|
end
|
399
534
|
|
@@ -402,7 +537,13 @@ describe CouchRest::Model do
|
|
402
537
|
view['rows'].length.should == 4
|
403
538
|
end
|
404
539
|
|
405
|
-
it "should
|
540
|
+
it "should not include non-Articles" do
|
541
|
+
Article.database.save({"date" => 1})
|
542
|
+
view = Article.by_date :raw => true
|
543
|
+
view['rows'].length.should == 4
|
544
|
+
end
|
545
|
+
|
546
|
+
it "should return the matching objects (with default argument :descending => true)" do
|
406
547
|
articles = Article.by_date
|
407
548
|
articles.collect{|a|a.title}.should == @titles.reverse
|
408
549
|
end
|
@@ -417,10 +558,9 @@ describe CouchRest::Model do
|
|
417
558
|
before(:all) do
|
418
559
|
Course.database.delete! rescue nil
|
419
560
|
@db = @cr.create_db(TESTDB) rescue nil
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
Course.new(:title => 'eee').save
|
561
|
+
%w{aaa bbb ddd eee}.each do |title|
|
562
|
+
Course.new(:title => title).save
|
563
|
+
end
|
424
564
|
end
|
425
565
|
it "should make the design doc upon first query" do
|
426
566
|
Course.by_title
|
@@ -442,13 +582,12 @@ describe CouchRest::Model do
|
|
442
582
|
courses = []
|
443
583
|
rs = Course.by_title # remove me
|
444
584
|
Course.view(:by_title) do |course|
|
445
|
-
# puts "course"
|
446
585
|
courses << course
|
447
586
|
end
|
448
|
-
# courses.should == 'x'
|
449
587
|
courses[0]["doc"]["title"].should =='aaa'
|
450
588
|
end
|
451
589
|
end
|
590
|
+
|
452
591
|
|
453
592
|
describe "a ducktype view" do
|
454
593
|
before(:all) do
|
@@ -494,7 +633,7 @@ describe CouchRest::Model do
|
|
494
633
|
articles[1].title.should == 'not junk'
|
495
634
|
end
|
496
635
|
it "should be queryable with couchrest options" do
|
497
|
-
articles = Article.by_user_id_and_date :
|
636
|
+
articles = Article.by_user_id_and_date :limit => 1, :startkey => 'quentin'
|
498
637
|
articles.length.should == 1
|
499
638
|
articles[0].title.should == "even more interesting"
|
500
639
|
end
|
@@ -527,6 +666,7 @@ describe CouchRest::Model do
|
|
527
666
|
end
|
528
667
|
end
|
529
668
|
|
669
|
+
# TODO: moved to Design, delete
|
530
670
|
describe "adding a view" do
|
531
671
|
before(:each) do
|
532
672
|
Article.by_date
|
@@ -544,10 +684,29 @@ describe CouchRest::Model do
|
|
544
684
|
Article.by_updated_at
|
545
685
|
newdocs = Article.database.documents :startkey => "_design/",
|
546
686
|
:endkey => "_design/\u9999"
|
687
|
+
# puts @design_docs.inspect
|
688
|
+
# puts newdocs.inspect
|
547
689
|
newdocs["rows"].length.should == @design_docs["rows"].length + 1
|
548
690
|
end
|
549
691
|
end
|
550
692
|
|
693
|
+
describe "with a lot of designs left around" do
|
694
|
+
before(:each) do
|
695
|
+
Article.by_date
|
696
|
+
Article.view_by :field
|
697
|
+
Article.by_field
|
698
|
+
end
|
699
|
+
it "should clean them up" do
|
700
|
+
Article.view_by :stream
|
701
|
+
Article.by_stream
|
702
|
+
ddocs = Article.all_design_doc_versions
|
703
|
+
ddocs["rows"].length.should > 1
|
704
|
+
Article.cleanup_design_docs!
|
705
|
+
ddocs = Article.all_design_doc_versions
|
706
|
+
ddocs["rows"].length.should == 1
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
551
710
|
describe "destroying an instance" do
|
552
711
|
before(:each) do
|
553
712
|
@obj = Basic.new
|
@@ -568,4 +727,129 @@ describe CouchRest::Model do
|
|
568
727
|
lambda{Basic.get(@obj.id)}.should raise_error
|
569
728
|
end
|
570
729
|
end
|
730
|
+
|
731
|
+
describe "#has_attachment?" do
|
732
|
+
before(:each) do
|
733
|
+
@obj = Basic.new
|
734
|
+
@obj.save.should == true
|
735
|
+
@file = File.open(FIXTURE_PATH + '/attachments/test.html')
|
736
|
+
@attachment_name = 'my_attachment'
|
737
|
+
@obj.create_attachment(:file => @file, :name => @attachment_name)
|
738
|
+
end
|
739
|
+
|
740
|
+
it 'should return false if there is no attachment' do
|
741
|
+
@obj.has_attachment?('bogus').should be_false
|
742
|
+
end
|
743
|
+
|
744
|
+
it 'should return true if there is an attachment' do
|
745
|
+
@obj.has_attachment?(@attachment_name).should be_true
|
746
|
+
end
|
747
|
+
|
748
|
+
it 'should return true if an object with an attachment is reloaded' do
|
749
|
+
@obj.save.should be_true
|
750
|
+
reloaded_obj = Basic.get(@obj.id)
|
751
|
+
reloaded_obj.has_attachment?(@attachment_name).should be_true
|
752
|
+
end
|
753
|
+
|
754
|
+
it 'should return false if an attachment has been removed' do
|
755
|
+
@obj.delete_attachment(@attachment_name)
|
756
|
+
@obj.has_attachment?(@attachment_name).should be_false
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
describe "creating an attachment" do
|
761
|
+
before(:each) do
|
762
|
+
@obj = Basic.new
|
763
|
+
@obj.save.should == true
|
764
|
+
@file_ext = File.open(FIXTURE_PATH + '/attachments/test.html')
|
765
|
+
@file_no_ext = File.open(FIXTURE_PATH + '/attachments/README')
|
766
|
+
@attachment_name = 'my_attachment'
|
767
|
+
@content_type = 'media/mp3'
|
768
|
+
end
|
769
|
+
|
770
|
+
it "should create an attachment from file with an extension" do
|
771
|
+
@obj.create_attachment(:file => @file_ext, :name => @attachment_name)
|
772
|
+
@obj.save.should == true
|
773
|
+
reloaded_obj = Basic.get(@obj.id)
|
774
|
+
reloaded_obj['_attachments'][@attachment_name].should_not be_nil
|
775
|
+
end
|
776
|
+
|
777
|
+
it "should create an attachment from file without an extension" do
|
778
|
+
@obj.create_attachment(:file => @file_no_ext, :name => @attachment_name)
|
779
|
+
@obj.save.should == true
|
780
|
+
reloaded_obj = Basic.get(@obj.id)
|
781
|
+
reloaded_obj['_attachments'][@attachment_name].should_not be_nil
|
782
|
+
end
|
783
|
+
|
784
|
+
it 'should raise ArgumentError if :file is missing' do
|
785
|
+
lambda{ @obj.create_attachment(:name => @attachment_name) }.should raise_error
|
786
|
+
end
|
787
|
+
|
788
|
+
it 'should raise ArgumentError if :name is missing' do
|
789
|
+
lambda{ @obj.create_attachment(:file => @file_ext) }.should raise_error
|
790
|
+
end
|
791
|
+
|
792
|
+
it 'should set the content-type if passed' do
|
793
|
+
@obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
|
794
|
+
@obj['_attachments'][@attachment_name]['content-type'].should == @content_type
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
describe 'reading, updating, and deleting an attachment' do
|
799
|
+
before(:each) do
|
800
|
+
@obj = Basic.new
|
801
|
+
@file = File.open(FIXTURE_PATH + '/attachments/test.html')
|
802
|
+
@attachment_name = 'my_attachment'
|
803
|
+
@obj.create_attachment(:file => @file, :name => @attachment_name)
|
804
|
+
@obj.save.should == true
|
805
|
+
@file.rewind
|
806
|
+
@content_type = 'media/mp3'
|
807
|
+
end
|
808
|
+
|
809
|
+
it 'should read an attachment that exists' do
|
810
|
+
@obj.read_attachment(@attachment_name).should == @file.read
|
811
|
+
end
|
812
|
+
|
813
|
+
it 'should update an attachment that exists' do
|
814
|
+
file = File.open(FIXTURE_PATH + '/attachments/README')
|
815
|
+
@file.should_not == file
|
816
|
+
@obj.update_attachment(:file => file, :name => @attachment_name)
|
817
|
+
@obj.save
|
818
|
+
reloaded_obj = Basic.get(@obj.id)
|
819
|
+
file.rewind
|
820
|
+
reloaded_obj.read_attachment(@attachment_name).should_not == @file.read
|
821
|
+
reloaded_obj.read_attachment(@attachment_name).should == file.read
|
822
|
+
end
|
823
|
+
|
824
|
+
it 'should se the content-type if passed' do
|
825
|
+
file = File.open(FIXTURE_PATH + '/attachments/README')
|
826
|
+
@file.should_not == file
|
827
|
+
@obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
|
828
|
+
@obj['_attachments'][@attachment_name]['content-type'].should == @content_type
|
829
|
+
end
|
830
|
+
|
831
|
+
it 'should delete an attachment that exists' do
|
832
|
+
@obj.delete_attachment(@attachment_name)
|
833
|
+
@obj.save
|
834
|
+
lambda{Basic.get(@obj.id).read_attachment(@attachment_name)}.should raise_error
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
describe "#attachment_url" do
|
839
|
+
before(:each) do
|
840
|
+
@obj = Basic.new
|
841
|
+
@file = File.open(FIXTURE_PATH + '/attachments/test.html')
|
842
|
+
@attachment_name = 'my_attachment'
|
843
|
+
@obj.create_attachment(:file => @file, :name => @attachment_name)
|
844
|
+
@obj.save.should == true
|
845
|
+
end
|
846
|
+
|
847
|
+
it 'should return nil if attachment does not exist' do
|
848
|
+
@obj.attachment_url('bogus').should be_nil
|
849
|
+
end
|
850
|
+
|
851
|
+
it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do
|
852
|
+
@obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
|
853
|
+
end
|
854
|
+
end
|
571
855
|
end
|
@@ -28,7 +28,7 @@ describe CouchRest::Pager do
|
|
28
28
|
end
|
29
29
|
@db.bulk_save(@docs)
|
30
30
|
end
|
31
|
-
it "should yield total_docs /
|
31
|
+
it "should yield total_docs / limit times" do
|
32
32
|
n = 0
|
33
33
|
@pager.all_docs(10) do |doc|
|
34
34
|
n += 1
|
@@ -76,7 +76,7 @@ describe CouchRest::Pager do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should have a view" do
|
79
|
-
@db.view('magic/number', :
|
79
|
+
@db.view('magic/number', :limit => 10)['rows'][0]['key'].should == 0
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should yield once per key" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
|
3
|
+
|
1
4
|
require File.dirname(__FILE__) + '/../lib/couchrest'
|
2
5
|
|
3
|
-
|
6
|
+
unless defined?(FIXTURE_PATH)
|
7
|
+
FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures'
|
8
|
+
SCRATCH_PATH = File.dirname(__FILE__) + '/tmp'
|
9
|
+
|
10
|
+
COUCHHOST = "http://127.0.0.1:5984"
|
11
|
+
TESTDB = 'couchrest-test'
|
12
|
+
end
|
4
13
|
|
5
|
-
|
6
|
-
|
14
|
+
def reset_test_db!
|
15
|
+
cr = CouchRest.new(COUCHHOST)
|
16
|
+
db = cr.database(TESTDB)
|
17
|
+
db.delete! rescue nil
|
18
|
+
db = cr.create_db(TESTDB) rescue nin
|
19
|
+
db
|
20
|
+
end
|
data/utils/remap.rb
CHANGED
@@ -2,11 +2,11 @@ require 'rubygems'
|
|
2
2
|
require 'couchrest'
|
3
3
|
|
4
4
|
# set the source db and map view
|
5
|
-
source = CouchRest.new("http://
|
5
|
+
source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
|
6
6
|
source_view = 'mydesign/view-map'
|
7
7
|
|
8
8
|
# set the target db
|
9
|
-
target = CouchRest.new("http://
|
9
|
+
target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
|
10
10
|
|
11
11
|
|
12
12
|
pager = CouchRest::Pager.new(source)
|
data/utils/subset.rb
CHANGED
@@ -5,10 +5,10 @@ require 'couchrest'
|
|
5
5
|
# use it to create a smaller dataset on which to prototype views.
|
6
6
|
|
7
7
|
# specify the source database
|
8
|
-
source = CouchRest.new("http://
|
8
|
+
source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
|
9
9
|
|
10
10
|
# specify the target database
|
11
|
-
target = CouchRest.new("http://
|
11
|
+
target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
|
12
12
|
|
13
13
|
# pager efficiently yields all view rows
|
14
14
|
pager = CouchRest::Pager.new(source)
|