mattetti-couchrest 0.33 → 0.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -66,7 +66,7 @@ describe "ExtendedDocument attachments" do
66
66
 
67
67
  it 'should set the content-type if passed' do
68
68
  @obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
69
- @obj['_attachments'][@attachment_name]['content-type'].should == @content_type
69
+ @obj['_attachments'][@attachment_name]['content_type'].should == @content_type
70
70
  end
71
71
  end
72
72
 
@@ -100,7 +100,7 @@ describe "ExtendedDocument attachments" do
100
100
  file = File.open(FIXTURE_PATH + '/attachments/README')
101
101
  @file.should_not == file
102
102
  @obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
103
- @obj['_attachments'][@attachment_name]['content-type'].should == @content_type
103
+ @obj['_attachments'][@attachment_name]['content_type'].should == @content_type
104
104
  end
105
105
 
106
106
  it 'should delete an attachment that exists' do
@@ -1,7 +1,7 @@
1
1
  require File.expand_path("../../../spec_helper", __FILE__)
2
2
  require File.join(FIXTURE_PATH, 'more', 'article')
3
3
  require File.join(FIXTURE_PATH, 'more', 'course')
4
-
4
+ require File.join(FIXTURE_PATH, 'more', 'cat')
5
5
 
6
6
  describe "ExtendedDocument" do
7
7
 
@@ -17,8 +17,11 @@ describe "ExtendedDocument" do
17
17
  end
18
18
 
19
19
  class WithCallBacks < CouchRest::ExtendedDocument
20
+ include ::CouchRest::Validation
20
21
  use_database TEST_SERVER.default_database
21
22
  property :name
23
+ property :run_before_validate
24
+ property :run_after_validate
22
25
  property :run_before_save
23
26
  property :run_after_save
24
27
  property :run_before_create
@@ -26,24 +29,56 @@ describe "ExtendedDocument" do
26
29
  property :run_before_update
27
30
  property :run_after_update
28
31
 
29
- save_callback :before do |object|
32
+ before_validate do |object|
33
+ object.run_before_validate = true
34
+ end
35
+ after_validate do |object|
36
+ object.run_after_validate = true
37
+ end
38
+ before_save do |object|
30
39
  object.run_before_save = true
31
40
  end
32
- save_callback :after do |object|
41
+ after_save do |object|
33
42
  object.run_after_save = true
34
43
  end
35
- create_callback :before do |object|
44
+ before_create do |object|
36
45
  object.run_before_create = true
37
46
  end
38
- create_callback :after do |object|
47
+ after_create do |object|
39
48
  object.run_after_create = true
40
49
  end
41
- update_callback :before do |object|
50
+ before_update do |object|
42
51
  object.run_before_update = true
43
52
  end
44
- update_callback :after do |object|
53
+ after_update do |object|
45
54
  object.run_after_update = true
46
55
  end
56
+
57
+ property :run_one
58
+ property :run_two
59
+ property :run_three
60
+
61
+ before_save :run_one_method, :run_two_method do |object|
62
+ object.run_three = true
63
+ end
64
+ def run_one_method
65
+ self.run_one = true
66
+ end
67
+ def run_two_method
68
+ self.run_two = true
69
+ end
70
+
71
+ attr_accessor :run_it
72
+ property :conditional_one
73
+ property :conditional_two
74
+
75
+ before_save :conditional_one_method, :conditional_two_method, :if => proc { self.run_it }
76
+ def conditional_one_method
77
+ self.conditional_one = true
78
+ end
79
+ def conditional_two_method
80
+ self.conditional_two = true
81
+ end
47
82
  end
48
83
 
49
84
  class WithTemplateAndUniqueID < CouchRest::ExtendedDocument
@@ -85,15 +120,12 @@ describe "ExtendedDocument" do
85
120
  end
86
121
 
87
122
  describe "a new model" do
88
- it "should be a new_record" do
89
- @obj = Basic.new
90
- @obj.rev.should be_nil
91
- @obj.should be_a_new_record
92
- end
93
- it "should be a new_document" do
123
+ it "should be a new document" do
94
124
  @obj = Basic.new
95
125
  @obj.rev.should be_nil
96
- @obj.should be_a_new_document
126
+ @obj.should be_new
127
+ @obj.should be_new_document
128
+ @obj.should be_new_record
97
129
  end
98
130
  end
99
131
 
@@ -101,7 +133,7 @@ describe "ExtendedDocument" do
101
133
  it "should instantialize and save a document" do
102
134
  article = Article.create(:title => 'my test')
103
135
  article.title.should == 'my test'
104
- article.should_not be_new_document
136
+ article.should_not be_new
105
137
  end
106
138
 
107
139
  it "should trigger the create callbacks" do
@@ -125,6 +157,27 @@ describe "ExtendedDocument" do
125
157
  @art.update_attributes_without_saving('date' => Time.now, :title => "super danger")
126
158
  @art['title'].should == "super danger"
127
159
  end
160
+ it "should silently ignore _id" do
161
+ @art.update_attributes_without_saving('_id' => 'foobar')
162
+ @art['_id'].should_not == 'foobar'
163
+ end
164
+ it "should silently ignore _rev" do
165
+ @art.update_attributes_without_saving('_rev' => 'foobar')
166
+ @art['_rev'].should_not == 'foobar'
167
+ end
168
+ it "should silently ignore created_at" do
169
+ @art.update_attributes_without_saving('created_at' => 'foobar')
170
+ @art['created_at'].should_not == 'foobar'
171
+ end
172
+ it "should silently ignore updated_at" do
173
+ @art.update_attributes_without_saving('updated_at' => 'foobar')
174
+ @art['updated_at'].should_not == 'foobar'
175
+ end
176
+ it "should also work using attributes= alias" do
177
+ @art.respond_to?(:attributes=).should be_true
178
+ @art.attributes = {'date' => Time.now, :title => "something else"}
179
+ @art['title'].should == "something else"
180
+ end
128
181
 
129
182
  it "should flip out if an attribute= method is missing" do
130
183
  lambda {
@@ -409,6 +462,25 @@ describe "ExtendedDocument" do
409
462
  it "should set the type" do
410
463
  @sobj['couchrest-type'].should == 'Basic'
411
464
  end
465
+
466
+ describe "save!" do
467
+
468
+ before(:each) do
469
+ @sobj = Card.new(:first_name => "Marcos", :last_name => "Tapajós")
470
+ end
471
+
472
+ it "should return true if save the document" do
473
+ @sobj.save!.should == true
474
+ end
475
+
476
+ it "should raise error if don't save the document" do
477
+ @sobj.first_name = nil
478
+ lambda { @sobj.save!.should == true }.should raise_error(RuntimeError)
479
+ end
480
+
481
+ end
482
+
483
+
412
484
  end
413
485
 
414
486
  describe "saving a model with a unique_id configured" do
@@ -419,7 +491,7 @@ describe "ExtendedDocument" do
419
491
  end
420
492
 
421
493
  it "should be a new document" do
422
- @art.should be_a_new_document
494
+ @art.should be_new
423
495
  @art.title.should be_nil
424
496
  end
425
497
 
@@ -527,12 +599,46 @@ describe "ExtendedDocument" do
527
599
  @doc = WithCallBacks.new
528
600
  end
529
601
 
602
+
603
+ describe "validate" do
604
+ it "should run before_validate before validating" do
605
+ @doc.run_before_validate.should be_nil
606
+ @doc.should be_valid
607
+ @doc.run_before_validate.should be_true
608
+ end
609
+ it "should run after_validate after validating" do
610
+ @doc.run_after_validate.should be_nil
611
+ @doc.should be_valid
612
+ @doc.run_after_validate.should be_true
613
+ end
614
+ end
530
615
  describe "save" do
531
616
  it "should run the after filter after saving" do
532
617
  @doc.run_after_save.should be_nil
533
618
  @doc.save.should be_true
534
619
  @doc.run_after_save.should be_true
535
620
  end
621
+ it "should run the grouped callbacks before saving" do
622
+ @doc.run_one.should be_nil
623
+ @doc.run_two.should be_nil
624
+ @doc.run_three.should be_nil
625
+ @doc.save.should be_true
626
+ @doc.run_one.should be_true
627
+ @doc.run_two.should be_true
628
+ @doc.run_three.should be_true
629
+ end
630
+ it "should not run conditional callbacks" do
631
+ @doc.run_it = false
632
+ @doc.save.should be_true
633
+ @doc.conditional_one.should be_nil
634
+ @doc.conditional_two.should be_nil
635
+ end
636
+ it "should run conditional callbacks" do
637
+ @doc.run_it = true
638
+ @doc.save.should be_true
639
+ @doc.conditional_one.should be_true
640
+ @doc.conditional_two.should be_true
641
+ end
536
642
  end
537
643
  describe "create" do
538
644
  it "should run the before save filter when creating" do
@@ -585,4 +691,49 @@ describe "ExtendedDocument" do
585
691
  @doc.other_arg.should == "foo-foo"
586
692
  end
587
693
  end
694
+
695
+ describe "recursive validation on an extended document" do
696
+ before :each do
697
+ reset_test_db!
698
+ @cat = Cat.new(:name => 'Sockington')
699
+ end
700
+
701
+ it "should not save if a nested casted model is invalid" do
702
+ @cat.favorite_toy = CatToy.new
703
+ @cat.should_not be_valid
704
+ @cat.save.should be_false
705
+ lambda{@cat.save!}.should raise_error
706
+ end
707
+
708
+ it "should save when nested casted model is valid" do
709
+ @cat.favorite_toy = CatToy.new(:name => 'Squeaky')
710
+ @cat.should be_valid
711
+ @cat.save.should be_true
712
+ lambda{@cat.save!}.should_not raise_error
713
+ end
714
+
715
+ it "should not save when nested collection contains an invalid casted model" do
716
+ @cat.toys = [CatToy.new(:name => 'Feather'), CatToy.new]
717
+ @cat.should_not be_valid
718
+ @cat.save.should be_false
719
+ lambda{@cat.save!}.should raise_error
720
+ end
721
+
722
+ it "should save when nested collection contains valid casted models" do
723
+ @cat.toys = [CatToy.new(:name => 'feather'), CatToy.new(:name => 'ball-o-twine')]
724
+ @cat.should be_valid
725
+ @cat.save.should be_true
726
+ lambda{@cat.save!}.should_not raise_error
727
+ end
728
+
729
+ it "should not fail if the nested casted model doesn't have validation" do
730
+ Cat.property :trainer, :cast_as => 'Person'
731
+ Cat.validates_present :name
732
+ cat = Cat.new(:name => 'Mr Bigglesworth')
733
+ cat.trainer = Person.new
734
+ cat.trainer.validatable?.should be_false
735
+ cat.should be_valid
736
+ cat.save.should be_true
737
+ end
738
+ end
588
739
  end
@@ -348,12 +348,19 @@ describe "ExtendedDocument views" do
348
348
  describe "with a collection" do
349
349
  before(:all) do
350
350
  reset_test_db!
351
- @titles = ["very uniq one", "really interesting", "some fun",
351
+ titles = ["very uniq one", "really interesting", "some fun",
352
352
  "really awesome", "crazy bob", "this rocks", "super rad"]
353
- @titles.each_with_index do |title,i|
353
+ titles.each_with_index do |title,i|
354
354
  a = Article.new(:title => title, :date => Date.today)
355
355
  a.save
356
356
  end
357
+
358
+ titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
359
+ "yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
360
+ titles.each_with_index do |title,i|
361
+ a = Article.new(:title => title, :date => Date.today - 1)
362
+ a.save
363
+ end
357
364
  end
358
365
  require 'date'
359
366
  it "should return a proxy that looks like an array of 7 Article objects" do
@@ -373,10 +380,6 @@ describe "ExtendedDocument views" do
373
380
  a.should_not be_nil
374
381
  end
375
382
  end
376
- it "should have the amount of paginated pages" do
377
- articles = Article.by_date :key => Date.today
378
- articles.paginate(:per_page => 3).amount_pages.should == 3
379
- end
380
383
  it "should provide a class method to access the collection directly" do
381
384
  articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
382
385
  :key => Date.today, :include_docs => true)
@@ -421,6 +424,14 @@ describe "ExtendedDocument views" do
421
424
  lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
422
425
  lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
423
426
  end
427
+ it "should be able to span multiple keys" do
428
+ articles = Article.by_date :startkey => Date.today, :endkey => Date.today - 1
429
+ articles.paginate(:page => 1, :per_page => 3).size.should == 3
430
+ articles.paginate(:page => 2, :per_page => 3).size.should == 3
431
+ articles.paginate(:page => 3, :per_page => 3).size.should == 3
432
+ articles.paginate(:page => 4, :per_page => 3).size.should == 3
433
+ articles.paginate(:page => 5, :per_page => 3).size.should == 1
434
+ end
424
435
  end
425
436
 
426
437
  end
@@ -4,6 +4,7 @@ require File.join(FIXTURE_PATH, 'more', 'card')
4
4
  require File.join(FIXTURE_PATH, 'more', 'invoice')
5
5
  require File.join(FIXTURE_PATH, 'more', 'service')
6
6
  require File.join(FIXTURE_PATH, 'more', 'event')
7
+ require File.join(FIXTURE_PATH, 'more', 'cat')
7
8
 
8
9
 
9
10
  describe "ExtendedDocument properties" do
@@ -94,7 +95,7 @@ describe "ExtendedDocument properties" do
94
95
  @invoice.location = nil
95
96
  @invoice.should_not be_valid
96
97
  @invoice.save.should be_false
97
- @invoice.should be_new_document
98
+ @invoice.should be_new
98
99
  end
99
100
  end
100
101
 
@@ -132,14 +133,17 @@ describe "ExtendedDocument properties" do
132
133
  describe "casting" do
133
134
  describe "cast keys to any type" do
134
135
  before(:all) do
135
- event_doc = { :subject => "Some event", :occurs_at => Time.now }
136
+ event_doc = { :subject => "Some event", :occurs_at => Time.now, :end_date => Date.today }
136
137
  e = Event.database.save_doc event_doc
137
138
 
138
139
  @event = Event.get e['id']
139
140
  end
140
- it "should cast created_at to Time" do
141
+ it "should cast occurs_at to Time" do
141
142
  @event['occurs_at'].should be_an_instance_of(Time)
142
143
  end
144
+ it "should cast end_date to Date" do
145
+ @event['end_date'].should be_an_instance_of(Date)
146
+ end
143
147
  end
144
148
 
145
149
  describe "casting to Float object" do
@@ -191,5 +195,69 @@ describe "ExtendedDocument properties" do
191
195
  end
192
196
 
193
197
  end
198
+ end
199
+
200
+ describe "a newly created casted model" do
201
+ before(:each) do
202
+ reset_test_db!
203
+ @cat = Cat.new(:name => 'Toonces')
204
+ @squeaky_mouse = CatToy.new(:name => 'Squeaky')
205
+ end
206
+
207
+ describe "assigned assigned to a casted property" do
208
+ it "should have casted_by set to its parent" do
209
+ @squeaky_mouse.casted_by.should be_nil
210
+ @cat.favorite_toy = @squeaky_mouse
211
+ @squeaky_mouse.casted_by.should === @cat
212
+ end
213
+ end
214
+
215
+ describe "appended to a casted collection" do
216
+ it "should have casted_by set to its parent" do
217
+ @squeaky_mouse.casted_by.should be_nil
218
+ @cat.toys << @squeaky_mouse
219
+ @squeaky_mouse.casted_by.should === @cat
220
+ @cat.save
221
+ @cat.toys.first.casted_by.should === @cat
222
+ end
223
+ end
194
224
 
225
+ describe "list assigned to a casted collection" do
226
+ it "should have casted_by set on all elements" do
227
+ toy1 = CatToy.new(:name => 'Feather')
228
+ toy2 = CatToy.new(:name => 'Mouse')
229
+ @cat.toys = [toy1, toy2]
230
+ toy1.casted_by.should === @cat
231
+ toy2.casted_by.should === @cat
232
+ @cat.save
233
+ @cat = Cat.get(@cat.id)
234
+ @cat.toys[0].casted_by.should === @cat
235
+ @cat.toys[1].casted_by.should === @cat
236
+ end
237
+ end
195
238
  end
239
+
240
+ describe "a casted model retrieved from the database" do
241
+ before(:each) do
242
+ reset_test_db!
243
+ @cat = Cat.new(:name => 'Stimpy')
244
+ @cat.favorite_toy = CatToy.new(:name => 'Stinky')
245
+ @cat.toys << CatToy.new(:name => 'Feather')
246
+ @cat.toys << CatToy.new(:name => 'Mouse')
247
+ @cat.save
248
+ @cat = Cat.get(@cat.id)
249
+ end
250
+
251
+ describe "as a casted property" do
252
+ it "should already be casted_by its parent" do
253
+ @cat.favorite_toy.casted_by.should === @cat
254
+ end
255
+ end
256
+
257
+ describe "from a casted collection" do
258
+ it "should already be casted_by its parent" do
259
+ @cat.toys[0].casted_by.should === @cat
260
+ @cat.toys[1].casted_by.should === @cat
261
+ end
262
+ end
263
+ end
@@ -26,9 +26,9 @@ class Article < CouchRest::ExtendedDocument
26
26
 
27
27
  timestamps!
28
28
 
29
- save_callback :before, :generate_slug_from_title
29
+ before_save :generate_slug_from_title
30
30
 
31
31
  def generate_slug_from_title
32
- self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new_document?
32
+ self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new?
33
33
  end
34
34
  end