simply_stored 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2111 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
- require File.expand_path(File.dirname(__FILE__) + '/fixtures/couch')
3
-
4
- class CouchTest < Test::Unit::TestCase
5
- context "A simply stored couch instance" do
6
- setup do
7
- CouchPotato::Config.database_name = 'simply_stored_test'
8
- recreate_db
9
- end
10
-
11
- context "design documents" do
12
- should "delete all" do
13
- db = "http://127.0.0.1:5984/#{CouchPotato::Config.database_name}"
14
- assert_equal 0, SimplyStored::Couch.delete_all_design_documents(db)
15
- user = User.create
16
- Post.create(:user => user)
17
- user.posts
18
- assert_equal 1, SimplyStored::Couch.delete_all_design_documents(db)
19
- end
20
- end
21
-
22
- context "when creating instances" do
23
- should "populate the attributes" do
24
- user = User.create(:title => "Mr.", :name => "Host Master")
25
- assert_equal "Mr.", user.title
26
- assert_equal "Host Master", user.name
27
- end
28
-
29
- should "save the instance" do
30
- user = User.create(:title => "Mr.")
31
- assert !user.new_record?
32
- end
33
-
34
- context "with a bang" do
35
- should 'not raise an exception when saving succeeded' do
36
- assert_nothing_raised do
37
- User.create!(:title => "Mr.")
38
- end
39
- end
40
-
41
- should 'save the user' do
42
- user = User.create!(:title => "Mr.")
43
- assert !user.new_record?
44
- end
45
-
46
- should 'raise an error when the validations failed' do
47
- assert_raises(CouchPotato::Database::ValidationsFailedError) do
48
- User.create!(:title => nil)
49
- end
50
- end
51
- end
52
-
53
- context "with a block" do
54
- should 'call the block with the record' do
55
- user = User.create do |u|
56
- u.title = "Mr."
57
- end
58
-
59
- assert_equal "Mr.", user.title
60
- end
61
-
62
- should 'save the record' do
63
- user = User.create do |u|
64
- u.title = "Mr."
65
- end
66
- assert !user.new_record?
67
- end
68
-
69
- should 'assign attributes via the hash' do
70
- user = User.create(:title => "Mr.") do |u|
71
- u.name = "Host Master"
72
- end
73
-
74
- assert_equal "Mr.", user.title
75
- assert_equal "Host Master", user.name
76
- end
77
- end
78
- end
79
-
80
- context "when saving an instance" do
81
- should "um, save the instance" do
82
- user = User.new(:title => "Mr.")
83
- assert user.new_record?
84
- user.save
85
- assert !user.new_record?
86
- end
87
-
88
- context "when using save!" do
89
- should 'raise an exception when a validation isnt fulfilled' do
90
- user = User.new
91
- assert_raises(CouchPotato::Database::ValidationsFailedError) do
92
- user.save!
93
- end
94
- end
95
- end
96
-
97
- context "when using save(false)" do
98
- should "not run the validations" do
99
- user = User.new
100
- user.save(false)
101
- assert !user.new?
102
- assert !user.dirty?
103
- end
104
- end
105
- end
106
-
107
- context "when destroying an instance" do
108
- should "remove the instance" do
109
- user = User.create(:title => "Mr")
110
- assert_difference 'User.find(:all).size', -1 do
111
- user.destroy
112
- end
113
- end
114
-
115
- should 'return the frozen instance, brrrr' do
116
- user = User.create(:title => "Mr")
117
- assert_equal user, user.destroy
118
- end
119
- end
120
-
121
- context "when updating attributes" do
122
- should "merge in the updated attributes" do
123
- user = User.create(:title => "Mr.")
124
- user.update_attributes(:title => "Mrs.")
125
- assert_equal "Mrs.", user.title
126
- end
127
-
128
- should "save the instance" do
129
- user = User.create(:title => "Mr.")
130
- user.update_attributes(:title => "Mrs.")
131
- assert !user.dirty?
132
- end
133
- end
134
-
135
- context "when finding instances" do
136
- context "with find(:all)" do
137
- setup do
138
- User.create(:title => "Mr.")
139
- User.create(:title => "Mrs.")
140
- end
141
-
142
- should "return all instances" do
143
- assert_equal 2, User.find(:all).size
144
- end
145
-
146
- should "allow a limit" do
147
- assert_equal 1, User.find(:all, :limit => 1).size
148
- end
149
-
150
- should "allow to order the results" do
151
- assert_not_equal User.find(:all).map(&:id), User.find(:all, :order => :desc).map(&:id)
152
- assert_equal User.find(:all).map(&:id).reverse, User.find(:all, :order => :desc).map(&:id)
153
- end
154
- end
155
-
156
- context "to find all instances" do
157
- should 'generate a default find_all view' do
158
- assert User.respond_to?(:all_documents)
159
- end
160
-
161
- should 'return all the users when calling all' do
162
- User.create(:title => "Mr.")
163
- User.create(:title => "Mrs.")
164
- assert_equal 2, User.all.size
165
- end
166
- end
167
-
168
- context "to find one instance" do
169
- should 'return one user when calling first' do
170
- user = User.create(:title => "Mr.")
171
- assert_equal user, User.first
172
- end
173
-
174
- should 'understand the order' do
175
- assert_nothing_raised do
176
- User.first(:order => :desc)
177
- end
178
- end
179
-
180
- should 'return nil when no user found' do
181
- assert_nil User.first
182
- end
183
- end
184
-
185
- context "when finding with just an identifier" do
186
- should "find just one instance" do
187
- user = User.create(:title => "Mr.")
188
- assert User.find(user.id).kind_of?(User)
189
- end
190
-
191
- should 'raise an error when no record was found' do
192
- assert_raises(SimplyStored::RecordNotFound) do
193
- User.find('abc')
194
- end
195
- end
196
-
197
- should 'tell you which class failed to load something' do
198
- exception = nil
199
- begin
200
- User.find('abc')
201
- rescue SimplyStored::RecordNotFound => e
202
- exception = e
203
- end
204
- assert_equal "User could not be found with \"abc\"", exception.message
205
- end
206
-
207
- should 'raise an error when nil was specified' do
208
- assert_raises(SimplyStored::Error) do
209
- User.find(nil)
210
- end
211
- end
212
-
213
- should 'raise an error when the record was not of the expected type' do
214
- post = Post.create
215
- assert_raises(SimplyStored::RecordNotFound) do
216
- User.find(post.id)
217
- end
218
- end
219
- end
220
-
221
- context "with a find_by prefix" do
222
- setup do
223
- recreate_db
224
- end
225
-
226
- should "create a view for the called finder" do
227
- User.find_by_name("joe")
228
- assert User.respond_to?(:by_name)
229
- end
230
-
231
- should 'not create the view when it already exists' do
232
- User.expects(:view).never
233
- User.find_by_name_and_created_at("joe", 'foo')
234
- end
235
-
236
- should "create a method to prevent future loops through method_missing" do
237
- assert !User.respond_to?(:find_by_title)
238
- User.find_by_title("Mr.")
239
- assert User.respond_to?(:find_by_title)
240
- end
241
-
242
- should "call the generated view and return the result" do
243
- user = User.create(:homepage => "http://www.peritor.com", :title => "Mr.")
244
- assert_equal user, User.find_by_homepage("http://www.peritor.com")
245
- end
246
-
247
- should 'find only one instance when using find_by' do
248
- User.create(:title => "Mr.")
249
- assert User.find_by_title("Mr.").is_a?(User)
250
- end
251
-
252
- should "raise an error if the parameters don't match" do
253
- assert_raise(ArgumentError) do
254
- User.find_by_title()
255
- end
256
-
257
- assert_raise(ArgumentError) do
258
- User.find_by_title(1,2,3,4,5)
259
- end
260
- end
261
- end
262
-
263
- context "with a find_all_by prefix" do
264
- should "create a view for the called finder" do
265
- User.find_all_by_name("joe")
266
- assert User.respond_to?(:by_name)
267
- end
268
-
269
- should 'not create the view when it already exists' do
270
- User.expects(:view).never
271
- User.find_all_by_name_and_created_at("joe", "foo")
272
- end
273
-
274
- should "create a method to prevent future loops through method_missing" do
275
- assert !User.respond_to?(:find_all_by_foo_attribute)
276
- User.find_all_by_foo_attribute("Mr.")
277
- assert User.respond_to?(:find_all_by_foo_attribute)
278
- end
279
-
280
- should "call the generated view and return the result" do
281
- user = User.create(:homepage => "http://www.peritor.com", :title => "Mr.")
282
- assert_equal [user], User.find_all_by_homepage("http://www.peritor.com")
283
- end
284
-
285
- should "return an emtpy array if none found" do
286
- recreate_db
287
- assert_equal [], User.find_all_by_title('Mr. Magoooo')
288
- end
289
-
290
- should 'find all instances when using find_all_by' do
291
- User.create(:title => "Mr.")
292
- User.create(:title => "Mr.")
293
- assert_equal 2, User.find_all_by_title("Mr.").size
294
- end
295
-
296
- should "raise an error if the parameters don't match" do
297
- assert_raise(ArgumentError) do
298
- User.find_all_by_title()
299
- end
300
-
301
- assert_raise(ArgumentError) do
302
- User.find_all_by_title(1,2,3,4,5)
303
- end
304
- end
305
- end
306
- end
307
-
308
- context "when counting" do
309
- setup do
310
- recreate_db
311
- end
312
-
313
- context "when counting all" do
314
- should "return the number of objects in the database" do
315
- CountMe.create(:title => "Mr.")
316
- CountMe.create(:title => "Mrs.")
317
- assert_equal 2, CountMe.find(:all).size
318
- assert_equal 2, CountMe.count
319
- end
320
-
321
- should "only count the correct class" do
322
- CountMe.create(:title => "Mr.")
323
- DontCountMe.create(:title => 'Foo')
324
- assert_equal 1, CountMe.find(:all).size
325
- assert_equal 1, CountMe.count
326
- end
327
- end
328
-
329
- context "when counting by prefix" do
330
- should "return the number of matching objects" do
331
- CountMe.create(:title => "Mr.")
332
- CountMe.create(:title => "Mrs.")
333
- assert_equal 1, CountMe.find_all_by_title('Mr.').size
334
- assert_equal 1, CountMe.count_by_title('Mr.')
335
- end
336
-
337
- should "only count the correct class" do
338
- CountMe.create(:title => "Mr.")
339
- DontCountMe.create(:title => 'Mr.')
340
- assert_equal 1, CountMe.find_all_by_title('Mr.').size
341
- assert_equal 1, CountMe.count_by_title('Mr.')
342
- end
343
- end
344
-
345
- end
346
-
347
- context "with associations" do
348
- context "with belongs_to" do
349
- should "generate a view for the association" do
350
- assert Post.respond_to?(:association_post_belongs_to_user)
351
- end
352
-
353
- should "add the foreign key id to the referencing object" do
354
- user = User.create(:title => "Mr.")
355
- post = Post.create(:user => user)
356
-
357
- post = Post.find(post.id)
358
- assert_equal user.id, post.user_id
359
- end
360
-
361
- should "set also the foreign key id to nil if setting the referencing object to nil" do
362
- user = User.create(:title => "Mr.")
363
- post = Post.create(:user => user)
364
- post.user = nil
365
- post.save!
366
- assert_nil post.reload.user
367
- assert_nil post.reload.user_id
368
- end
369
-
370
- should "fetch the object from the database when requested through the getter" do
371
- user = User.create(:title => "Mr.")
372
- post = Post.create(:user => user)
373
-
374
- post = Post.find(post.id)
375
- assert_equal user, post.user
376
- end
377
-
378
- should "mark the referencing object as dirty" do
379
- user = User.create(:title => "Mr.")
380
- post = Post.create
381
- post.user = user
382
- assert post.dirty?
383
- end
384
-
385
- should "allow assigning a different object and store the id accordingly" do
386
- user = User.create(:title => "Mr.")
387
- user2 = User.create(:title => "Mrs.")
388
- post = Post.create(:user => user)
389
- post.user = user2
390
- post.save
391
-
392
- post = Post.find(post.id)
393
- assert_equal user2, post.user
394
- end
395
-
396
- should "check the class and raise an error if not matching in belongs_to setter" do
397
- post = Post.create
398
- assert_raise(ArgumentError, 'expected Post got String') do
399
- post.user = 'foo'
400
- end
401
- end
402
-
403
- should 'not query for the object twice in getter' do
404
- user = User.create(:title => "Mr.")
405
- post = Post.create(:user => user)
406
- post = Post.find(post.id)
407
- User.expects(:find).returns "user"
408
- post.user
409
- User.expects(:find).never
410
- post.user
411
- end
412
-
413
- should 'use cache in getter' do
414
- post = Post.create
415
- post.instance_variable_set("@user", 'foo')
416
- assert_equal 'foo', post.user
417
- end
418
-
419
- should "ignore the cache if force_reload is given as an option" do
420
- user = User.create(:name => 'Dude', :title => 'Mr.')
421
- post = Post.create(:user => user)
422
- post.reload
423
- post.instance_variable_set("@user", 'foo')
424
- assert_not_equal 'foo', post.user(:force_reload => true)
425
- end
426
-
427
- should 'set cache in setter' do
428
- post = Post.create
429
- user = User.create
430
- assert_nil post.instance_variable_get("@user")
431
- post.user = user
432
- assert_equal user, post.instance_variable_get("@user")
433
- end
434
-
435
- should "not hit the database when the id column is empty" do
436
- User.expects(:find).never
437
- post = Post.create
438
- post.user
439
- end
440
-
441
- should "know when the associated object changed" do
442
- post = Post.create(:user => User.create(:title => "Mr."))
443
- user2 = User.create(:title => "Mr.")
444
- post.user = user2
445
- assert post.user_changed?
446
- end
447
-
448
- should "not be changed when an association has not changed" do
449
- post = Post.create(:user => User.create(:title => "Mr."))
450
- assert !post.user_changed?
451
- end
452
-
453
- should "not be changed when assigned the same object" do
454
- user = User.create(:title => "Mr.")
455
- post = Post.create(:user => user)
456
- post.user = user
457
- assert !post.user_changed?
458
- end
459
-
460
- should "not be changed after saving" do
461
- user = User.create(:title => "Mr.")
462
- post = Post.new
463
- post.user = user
464
- assert post.user_changed?
465
- post.save!
466
- assert !post.user_changed?
467
- end
468
-
469
- should "handle a foreign_key of '' as nil" do
470
- post = Post.create
471
- post.user_id = ''
472
-
473
- assert_nothing_raised do
474
- assert_nil post.user
475
- end
476
- end
477
-
478
- context "with aliased associations" do
479
- should "allow different names for the same class" do
480
- editor = User.create(:name => 'Editor', :title => 'Dr.')
481
- author = User.create(:name => 'author', :title => 'Dr.')
482
- assert_not_nil editor.id, editor.errors.inspect
483
- assert_not_nil author.id, author.errors.inspect
484
-
485
- doc = Document.create(:editor => editor, :author => author)
486
- doc.save!
487
- assert_equal editor.id, doc.editor_id
488
- assert_equal author.id, doc.author_id
489
- doc = Document.find(doc.id)
490
- assert_not_nil doc.editor, doc.inspect
491
- assert_not_nil doc.author
492
- assert_equal editor.id, doc.editor.id
493
- assert_equal author.id, doc.author.id
494
- end
495
- end
496
- end
497
-
498
- context "with has_many" do
499
- should "create a fetch method for the associated objects" do
500
- user = User.new
501
- assert user.respond_to?(:posts)
502
- end
503
-
504
- should "fetch the associated objects" do
505
- user = User.create(:title => "Mr.")
506
- 3.times {
507
- post = Post.new
508
- post.user = user
509
- post.save!
510
- }
511
- assert_equal 3, user.posts.size
512
- user.posts
513
- end
514
-
515
- context "limit" do
516
-
517
- should "be able to limit the result set" do
518
- user = User.create(:title => "Mr.")
519
- 3.times {
520
- post = Post.new
521
- post.user = user
522
- post.save!
523
- }
524
- assert_equal 2, user.posts(:limit => 2).size
525
- end
526
-
527
- should "use the given options in the cache-key" do
528
- user = User.create(:title => "Mr.")
529
- 3.times {
530
- post = Post.new
531
- post.user = user
532
- post.save!
533
- }
534
- assert_equal 2, user.posts(:limit => 2).size
535
- assert_equal 3, user.posts(:limit => 3).size
536
- end
537
-
538
- should "be able to limit the result set - also for through objects" do
539
- @user = User.create(:title => "Mr.")
540
- first_pain = Pain.create
541
- frist_hemorrhoid = Hemorrhoid.create(:user => @user, :pain => first_pain)
542
- assert_equal [first_pain], @user.pains
543
- second_pain = Pain.create
544
- second_hemorrhoid = Hemorrhoid.create(:user => @user, :pain => second_pain)
545
- @user.reload
546
- assert_equal 2, @user.pains.size
547
- assert_equal 1, @user.pains(:limit => 1).size
548
- end
549
- end
550
-
551
- context "order" do
552
- setup do
553
- @user = User.create(:title => "Mr.")
554
- 3.times {
555
- post = Post.new
556
- post.user = @user
557
- post.save!
558
- }
559
- end
560
-
561
- should "support different order" do
562
- assert_nothing_raised do
563
- @user.posts(:order => :asc)
564
- end
565
-
566
- assert_nothing_raised do
567
- @user.posts(:order => :desc)
568
- end
569
- end
570
-
571
- should "reverse the order if :desc" do
572
- assert_equal @user.posts(:order => :asc).map(&:id).reverse, @user.posts(:order => :desc).map(&:id)
573
- end
574
-
575
- should "work with the limit option" do
576
- last_post = Post.create(:user => @user)
577
- assert_not_equal @user.posts(:order => :asc, :limit => 3).map(&:id).reverse, @user.posts(:order => :desc, :limit => 3).map(&:id)
578
- end
579
- end
580
-
581
- should "verify the given options for the accessor method" do
582
- user = User.create(:title => "Mr.")
583
- assert_raise(ArgumentError) do
584
- user.posts(:foo => false)
585
- end
586
- end
587
-
588
- should "verify the given options for the association defintion" do
589
- assert_raise(ArgumentError) do
590
- User.instance_eval do
591
- has_many :foo, :bar => :do
592
- end
593
- end
594
- end
595
-
596
- should "only fetch objects of the correct type" do
597
- user = User.create(:title => "Mr.")
598
- post = Post.new
599
- post.user = user
600
- post.save!
601
-
602
- comment = Comment.new
603
- comment.user = user
604
- comment.save!
605
-
606
- assert_equal 1, user.posts.size
607
- end
608
-
609
- should "getter should user cache" do
610
- user = User.create(:title => "Mr.")
611
- post = Post.new
612
- post.user = user
613
- post.save!
614
- user.posts
615
- assert_equal [post], user.instance_variable_get("@posts")[:all]
616
- end
617
-
618
- should "add methods to handle associated objects" do
619
- user = User.new(:title => "Mr.")
620
- assert user.respond_to?(:add_post)
621
- assert user.respond_to?(:remove_post)
622
- assert user.respond_to?(:remove_all_posts)
623
- end
624
-
625
- should 'ignore the cache when requesting explicit reload' do
626
- user = User.create(:title => "Mr.")
627
- assert_equal [], user.posts
628
- post = Post.new
629
- post.user = user
630
- post.save!
631
- assert_equal [post], user.posts(:force_reload => true)
632
- end
633
-
634
- context "when adding items" do
635
- should "add the item to the internal cache" do
636
- daddy = User.new(:title => "Mr.")
637
- item = Post.new
638
- assert_equal [], daddy.posts
639
- daddy.add_post(item)
640
- assert_equal [item], daddy.posts
641
- assert_equal [item], daddy.instance_variable_get("@posts")[:all]
642
- end
643
-
644
- should "raise an error when the added item is not an object of the expected class" do
645
- user = User.new
646
- assert_raise(ArgumentError, 'excepted Post got String') do
647
- user.add_post('foo')
648
- end
649
- end
650
-
651
- should "save the added item" do
652
- post = Post.new
653
- user = User.create(:title => "Mr.")
654
- user.add_post(post)
655
- assert !post.new_record?
656
- end
657
-
658
- should 'set the forein key on the added object' do
659
- post = Post.new
660
- user = User.create(:title => "Mr.")
661
- user.add_post(post)
662
- assert_equal user.id, post.user_id
663
- end
664
- end
665
-
666
- context "when removing items" do
667
- should "should unset the foreign key" do
668
- user = User.create(:title => "Mr.")
669
- post = Post.create(:user => user)
670
-
671
- user.remove_post(post)
672
- assert_nil post.user_id
673
- end
674
-
675
- should "remove the item from the cache" do
676
- user = User.create(:title => "Mr.")
677
- post = Post.create(:user => user)
678
- assert user.posts.include?(post)
679
- user.remove_post(post)
680
- assert !user.posts.any?{|p| post.id == p.id}
681
- assert_equal [], user.instance_variable_get("@posts")[:all]
682
- end
683
-
684
- should "save the removed item with the nullified foreign key" do
685
- user = User.create(:title => "Mr.")
686
- post = Post.create(:user => user)
687
-
688
- user.remove_post(post)
689
- post = Post.find(post.id)
690
- assert_nil post.user_id
691
- end
692
-
693
- should 'raise an error when another object is the owner of the object to be removed' do
694
- user = User.create(:title => "Mr.")
695
- mrs = User.create(:title => "Mrs.")
696
- post = Post.create(:user => user)
697
- assert_raise(ArgumentError) do
698
- mrs.remove_post(post)
699
- end
700
- end
701
-
702
- should 'raise an error when the object is the wrong type' do
703
- user = User.new
704
- assert_raise(ArgumentError, 'excepted Post got String') do
705
- user.remove_post('foo')
706
- end
707
- end
708
-
709
- should "delete the object when dependent:destroy" do
710
- Category.instance_eval do
711
- has_many :tags, :dependent => :destroy
712
- end
713
-
714
- category = Category.create(:name => "food")
715
- tag = Tag.create(:name => "food", :category => category)
716
- assert !tag.new?
717
- category.remove_tag(tag)
718
-
719
- assert_equal [], Tag.find(:all)
720
- end
721
-
722
- should "not nullify or delete dependents if the options is set to :ignore when removing" do
723
- master = Master.create
724
- master_id = master.id
725
- servant = Servant.create(:master => master)
726
- master.remove_servant(servant)
727
- assert_equal master_id, servant.reload.master_id
728
- end
729
-
730
- should "not nullify or delete dependents if the options is set to :ignore when deleting" do
731
- master = Master.create
732
- master_id = master.id
733
- servant = Servant.create(:master => master)
734
- master.destroy
735
- assert_equal master_id, servant.reload.master_id
736
- end
737
-
738
- end
739
-
740
- context "when removing all items" do
741
- should 'nullify the foreign keys on all referenced items' do
742
- user = User.create(:title => "Mr.")
743
- post = Post.create(:user => user)
744
- post2 = Post.create(:user => user)
745
- user.remove_all_posts
746
- post = Post.find(post.id)
747
- post2 = Post.find(post2.id)
748
- assert_nil post.user_id
749
- assert_nil post2.user_id
750
- end
751
-
752
- should 'empty the cache' do
753
- user = User.create(:title => "Mr.")
754
- post = Post.create(:user => user)
755
- post2 = Post.create(:user => user)
756
- user.remove_all_posts
757
- assert_equal [], user.posts
758
- assert_equal [], user.instance_variable_get("@posts")[:all]
759
- end
760
-
761
- context "when counting" do
762
- setup do
763
- @user = User.create(:title => "Mr.")
764
- end
765
-
766
- should "define a count method" do
767
- assert @user.respond_to?(:post_count)
768
- end
769
-
770
- should "cache the result" do
771
- assert_equal 0, @user.post_count
772
- Post.create(:user => @user)
773
- assert_equal 0, @user.post_count
774
- assert_equal 0, @user.instance_variable_get("@post_count")
775
- @user.instance_variable_set("@post_count", nil)
776
- assert_equal 1, @user.post_count
777
- end
778
-
779
- should "force reload even if cached" do
780
- assert_equal 0, @user.post_count
781
- Post.create(:user => @user)
782
- assert_equal 0, @user.post_count
783
- assert_equal 1, @user.post_count(:force_reload => true)
784
- end
785
-
786
- should "count the number of belongs_to objects" do
787
- assert_equal 0, @user.post_count(:force_reload => true)
788
- Post.create(:user => @user)
789
- assert_equal 1, @user.post_count(:force_reload => true)
790
- Post.create(:user => @user)
791
- assert_equal 2, @user.post_count(:force_reload => true)
792
- end
793
-
794
- should "not count foreign objects" do
795
- assert_equal 0, @user.post_count
796
- Post.create(:user => nil)
797
- Post.create(:user => User.create(:title => 'Doc'))
798
- assert_equal 0, @user.post_count
799
- assert_equal 2, Post.count
800
- end
801
-
802
- should "not count delete objects" do
803
- hemorrhoid = Hemorrhoid.create(:user => @user)
804
- assert_equal 1, @user.hemorrhoid_count
805
- hemorrhoid.delete
806
- assert_equal 0, @user.hemorrhoid_count(:force_reload => true)
807
- assert_equal 1, @user.hemorrhoid_count(:force_reload => true, :with_deleted => true)
808
- end
809
-
810
- should "work with has_many :through" do
811
- assert_equal 0, @user.pain_count
812
- first_pain = Pain.create
813
- frist_hemorrhoid = Hemorrhoid.create(:user => @user, :pain => first_pain)
814
- assert_equal [first_pain], @user.pains
815
- assert_equal 1, @user.pain_count(:force_reload => true)
816
-
817
- second_pain = Pain.create
818
- second_hemorrhoid = Hemorrhoid.create(:user => @user, :pain => second_pain)
819
- assert_equal 2, @user.pain_count(:force_reload => true)
820
- end
821
-
822
- end
823
- end
824
-
825
- context 'when destroying the parent objects' do
826
- should "delete relations when dependent is destroy" do
827
- Category.instance_eval do
828
- has_many :tags, :dependent => :destroy
829
- end
830
-
831
- category = Category.create(:name => "food")
832
- tag = Tag.create(:name => "food", :category => category)
833
-
834
- assert_equal [tag], Tag.find(:all)
835
- category.destroy
836
- assert_equal [], Tag.find(:all)
837
- end
838
-
839
- should "nullify relations when dependent is nullify" do
840
-
841
- user = User.create(:title => "Mr.")
842
- post = Post.create(:user => user)
843
-
844
- user.destroy
845
- post = Post.find(post.id)
846
- assert_nil post.user_id
847
- end
848
-
849
- should "nullify the foreign key even if validation forbids" do
850
- user = User.create(:title => "Mr.")
851
- post = StrictPost.create(:user => user)
852
-
853
- user.destroy
854
- post = StrictPost.find(post.id)
855
- assert_nil post.user_id
856
- end
857
- end
858
- end
859
-
860
- context "with has_many :trough" do
861
- setup do
862
- @journal_1 = Journal.create
863
- @journal_2 = Journal.create
864
- @reader_1 = Reader.create
865
- @reader_2 = Reader.create
866
- end
867
-
868
- should "raise an exception if there is no :through relation" do
869
-
870
- assert_raise(ArgumentError) do
871
- class FooHasManyThroughBar
872
- include SimplyStored::Couch
873
- has_many :foos, :through => :bars
874
- end
875
- end
876
- end
877
-
878
- should "define a getter" do
879
- assert @journal_1.respond_to?(:readers)
880
- assert @reader_1.respond_to?(:journals)
881
- end
882
-
883
- should "load the objects through" do
884
- membership = Membership.new
885
- membership.journal = @journal_1
886
- membership.reader = @reader_1
887
- assert membership.save
888
-
889
- assert_equal @journal_1, membership.journal
890
- assert_equal @reader_1, membership.reader
891
- assert_equal [membership], @journal_1.reload.memberships
892
- assert_equal [membership], @journal_1.reload.memberships
893
-
894
- assert_equal [@reader_1], @journal_1.readers
895
- assert_equal [@journal_1], @reader_1.journals
896
-
897
- membership_2 = Membership.new
898
- membership_2.journal = @journal_1
899
- membership_2.reader = @reader_2
900
- assert membership_2.save
901
-
902
- assert_equal [@reader_1.id, @reader_2.id].sort, @journal_1.reload.readers.map(&:id).sort
903
- assert_equal [@journal_1.id], @reader_1.reload.journals.map(&:id).sort
904
- assert_equal [@journal_1.id], @reader_2.reload.journals.map(&:id).sort
905
-
906
- membership_3 = Membership.new
907
- membership_3.journal = @journal_2
908
- membership_3.reader = @reader_2
909
- assert membership_3.save
910
-
911
- assert_equal [@reader_1.id, @reader_2.id].sort, @journal_1.reload.readers.map(&:id).sort
912
- assert_equal [@reader_2.id].sort, @journal_2.reload.readers.map(&:id).sort
913
- assert_equal [@journal_1.id], @reader_1.reload.journals.map(&:id).sort
914
- assert_equal [@journal_1.id, @journal_2.id].sort, @reader_2.reload.journals.map(&:id).sort
915
-
916
- membership_3.destroy
917
-
918
- assert_equal [@reader_1.id, @reader_2.id].sort, @journal_1.reload.readers.map(&:id).sort
919
- assert_equal [], @journal_2.reload.readers
920
- assert_equal [@journal_1.id], @reader_1.reload.journals.map(&:id).sort
921
- assert_equal [@journal_1.id], @reader_2.reload.journals.map(&:id).sort
922
- end
923
-
924
- should "verify the given options" do
925
- assert_raise(ArgumentError) do
926
- @journal_1.readers(:foo => true)
927
- end
928
- end
929
-
930
- should "not try to destroy/nullify through-objects on parent object delete" do
931
- membership = Membership.new
932
- membership.journal = @journal_1
933
- membership.reader = @reader_1
934
- assert membership.save
935
-
936
- @reader_1.reload
937
- @journal_1.reload
938
-
939
- Reader.any_instance.expects("journal=").never
940
- Journal.any_instance.expects(:readers).never
941
-
942
- @journal_1.delete
943
- end
944
-
945
- end
946
-
947
- context "with has_one" do
948
-
949
- should "add a getter method" do
950
- assert Instance.new.respond_to?(:identity)
951
- end
952
-
953
- should "fetch the object when invoking the getter" do
954
- instance = Instance.create
955
- identity = Identity.create(:instance => instance)
956
- assert_equal identity, instance.identity
957
- end
958
-
959
- should "verify the given options for the accessor method" do
960
- instance = Instance.create
961
- assert_raise(ArgumentError) do
962
- instance.identity(:foo => :var)
963
- end
964
- end
965
-
966
- should "verify the given options for the association defintion" do
967
- assert_raise(ArgumentError) do
968
- User.instance_eval do
969
- has_one :foo, :bar => :do
970
- end
971
- end
972
- end
973
-
974
- should "store the fetched object into the cache" do
975
- instance = Instance.create
976
- identity = Identity.create(:instance => instance)
977
- instance.identity
978
- assert_equal identity, instance.instance_variable_get("@identity")
979
- end
980
-
981
- should "not fetch from the database when object is in cache" do
982
- instance = Instance.create
983
- identity = Identity.create(:instance => instance)
984
- instance.identity
985
- CouchPotato.database.expects(:view).never
986
- instance.identity
987
- end
988
-
989
- should "update the foreign object to have the owner's id in the forein key" do
990
- instance = Instance.create
991
- identity = Identity.create
992
- instance.identity = identity
993
- identity.reload
994
- assert_equal instance.id, identity.instance_id
995
- end
996
-
997
- should "update the cache when setting" do
998
- instance = Instance.create
999
- identity = Identity.create
1000
- instance.identity = identity
1001
- CouchPotato.expects(:database).never
1002
- assert_equal identity, instance.identity
1003
- end
1004
-
1005
- should "set the foreign key value to nil when assigning nil" do
1006
- instance = Instance.create
1007
- identity = Identity.create(:instance => instance)
1008
- instance.identity = nil
1009
- identity = Identity.find(identity.id)
1010
- assert_nil identity.instance_id
1011
- end
1012
-
1013
- should 'check the class' do
1014
- instance = Instance.create
1015
- assert_raise(ArgumentError, 'expected Item got String') do
1016
- instance.identity = 'foo'
1017
- end
1018
- end
1019
-
1020
- should 'delete the dependent objects when dependent is set to destroy' do
1021
- identity = Identity.create
1022
- mag = Magazine.create
1023
- mag.identity = identity
1024
- mag.identity = nil
1025
- assert_nil Identity.find_by_id(identity.id)
1026
- end
1027
-
1028
- should 'unset the id on the foreign object when a new object is set' do
1029
- instance = Instance.create
1030
- identity = Identity.create(:instance => instance)
1031
- identity2 = Identity.create
1032
-
1033
- instance.identity = identity2
1034
- identity = Identity.find(identity.id)
1035
- assert_nil identity.instance_id
1036
- end
1037
-
1038
- should 'delete the foreign object when a new object is set and dependent is set to destroy' do
1039
- identity = Identity.create
1040
- identity2 = Identity.create
1041
- mag = Magazine.create
1042
- mag.identity = identity
1043
- mag.identity = identity2
1044
- assert_nil Identity.find_by_id(identity.id)
1045
- end
1046
-
1047
- should 'delete the foreign object when parent is destroyed and dependent is set to destroy' do
1048
- identity = Identity.create
1049
- mag = Magazine.create
1050
- mag.identity = identity
1051
-
1052
- mag.destroy
1053
- assert_nil Identity.find_by_id(identity.id)
1054
- end
1055
-
1056
- should 'nullify the foreign objects foreign key when parent is destroyed' do
1057
- identity = Identity.create
1058
- instance = Instance.create
1059
- instance.identity = identity
1060
- instance.destroy
1061
- identity = Identity.find(identity.id)
1062
- assert_nil identity.instance_id
1063
- end
1064
- end
1065
- end
1066
-
1067
- context "attribute proctection against mass assignment" do
1068
-
1069
- context "when using attr_protected" do
1070
- setup do
1071
- Category.instance_eval do
1072
- @_accessible_attributes = []
1073
- attr_protected :parent, :alias
1074
- end
1075
- end
1076
-
1077
- should "not allow to set with mass assignment using attributes=" do
1078
- item = Category.new
1079
- item.attributes = {:parent => 'a', :name => 'c'}
1080
- assert_equal 'c', item.name
1081
- assert_nil item.parent
1082
- end
1083
-
1084
- should "not allow to set with mass assignment using attributes= - ignore string vs. symbol" do
1085
- item = Category.new
1086
- item.attributes = {'parent' => 'a', 'name' => 'c'}
1087
- assert_equal 'c', item.name
1088
- assert_nil item.parent
1089
- end
1090
-
1091
- should "not allow to set with mass assignment using the constructor" do
1092
- item = Category.new(:parent => 'a', :name => 'c')
1093
- assert_equal 'c', item.name
1094
- assert_nil item.parent
1095
- end
1096
-
1097
- should "not allow to set with mass assignment using update_attributes" do
1098
- item = Category.new
1099
- item.update_attributes(:parent => 'a', :name => 'c')
1100
- assert_equal 'c', item.name
1101
- assert_nil item.parent
1102
- end
1103
- end
1104
-
1105
- context "attr_accessible" do
1106
- setup do
1107
- Category.instance_eval do
1108
- @_protected_attributes = []
1109
- attr_accessible :name
1110
- end
1111
- end
1112
-
1113
- should "not allow to set with mass assignment using attributes=" do
1114
- item = Category.new
1115
- item.attributes = {:parent => 'a', :name => 'c'}
1116
- assert_equal 'c', item.name
1117
- assert_nil item.parent
1118
- end
1119
-
1120
- should "not allow to set with mass assignment using the constructor" do
1121
- item = Category.new(:parent => 'a', :name => 'c')
1122
- assert_equal 'c', item.name
1123
- assert_nil item.parent
1124
- end
1125
-
1126
- should "not allow to set with mass assignment using update_attributes" do
1127
- item = Category.new
1128
- item.update_attributes(:parent => 'a', :name => 'c')
1129
- # item.reload
1130
- assert_equal 'c', item.name
1131
- assert_nil item.parent
1132
- end
1133
- end
1134
- end
1135
-
1136
- context "with additional validations" do
1137
- context "with validates_inclusion_of" do
1138
- should "validate inclusion of an attribute in an array" do
1139
- category = Category.new(:name => "other")
1140
- assert !category.save
1141
- end
1142
-
1143
- should "validate when the attribute is an array" do
1144
- category = Category.new(:name => ['drinks', 'food'])
1145
- assert_nothing_raised do
1146
- category.save!
1147
- end
1148
- end
1149
-
1150
- should "add an error message" do
1151
- category = Category.new(:name => "other")
1152
- category.valid?
1153
- assert_match(/must be one or more of food, drinks, party/, category.errors.full_messages.first)
1154
- end
1155
-
1156
- should "allow blank" do
1157
- category = Category.new(:name => nil)
1158
- assert category.valid?
1159
- end
1160
- end
1161
-
1162
- context "with validates_format_of" do
1163
- class ValidatedUser
1164
- include SimplyStored::Couch
1165
- property :name
1166
- validates_format_of :name, :with => /Paul/
1167
- end
1168
-
1169
- should 'validate the format and fail when not matched' do
1170
- user = ValidatedUser.new(:name => "John")
1171
- assert !user.valid?
1172
- end
1173
-
1174
- should 'succeed when matched' do
1175
- user = ValidatedUser.new(:name => "Paul")
1176
- assert user.valid?
1177
- end
1178
-
1179
- should 'fail when empty' do
1180
- user = ValidatedUser.new(:name => nil)
1181
- assert !user.valid?
1182
- end
1183
-
1184
- context "with allow_blank" do
1185
- class ValidatedBlankUser
1186
- include SimplyStored::Couch
1187
- property :name
1188
- validates_format_of :name, :with => /Paul/, :allow_blank => true
1189
- end
1190
-
1191
- should 'not fail when nil' do
1192
- user = ValidatedBlankUser.new(:name => nil)
1193
- assert user.valid?
1194
- end
1195
-
1196
- should 'not fail when empty string' do
1197
- user = ValidatedBlankUser.new(:name => '')
1198
- assert user.valid?
1199
- end
1200
-
1201
- should 'fail when not matching' do
1202
- user = ValidatedBlankUser.new(:name => 'John')
1203
- assert !user.valid?
1204
- end
1205
-
1206
- should 'not fail when matching' do
1207
- user = ValidatedBlankUser.new(:name => 'Paul')
1208
- assert user.valid?
1209
- end
1210
-
1211
- end
1212
- end
1213
-
1214
- context "with validates_uniqueness_of" do
1215
- should "add a view on the unique attribute" do
1216
- assert UniqueUser.by_name
1217
- end
1218
-
1219
- should "set an error when a different with the same instance exists" do
1220
- assert UniqueUser.create(:name => "Host Master")
1221
- user = UniqueUser.create(:name => "Host Master")
1222
- assert !user.valid?
1223
- end
1224
-
1225
- should "not have an error when we're the only one around" do
1226
- user = UniqueUser.create(:name => "Host Master")
1227
- assert !user.new_record?
1228
- end
1229
-
1230
- should "not have an error when it's the same instance" do
1231
- user = UniqueUser.create(:name => "Host Master")
1232
- user = UniqueUser.find(user.id)
1233
- assert user.valid?
1234
- end
1235
-
1236
- should 'have a nice error message' do
1237
- assert UniqueUser.create(:name => "Host Master")
1238
- user = UniqueUser.create(:name => "Host Master")
1239
- assert_equal "Name is already taken", user.errors.on(:name)
1240
- end
1241
-
1242
- should 'create a view to check with' do
1243
- assert UniqueUser.respond_to?(:by_name)
1244
- assert_equal :name, UniqueUser.by_name.send(:options)[:key]
1245
- end
1246
-
1247
- should 'not overwrite the view when a custom one already exists' do
1248
- assert_equal :email, UniqueUserWithAView.by_name.send(:options)[:key]
1249
- end
1250
- end
1251
- end
1252
-
1253
- context "when reloading an instance" do
1254
- should "reload new attributes from the database" do
1255
- user = User.create(:title => "Mr.", :name => "Host Master")
1256
- user2 = User.find(user.id)
1257
- user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
1258
- user.reload
1259
- assert_equal "Mrs.", user.title
1260
- assert_equal "Hostess Masteress", user.name
1261
- end
1262
-
1263
- should "remove attributes that are no longer in the database" do
1264
- user = User.create(:title => "Mr.", :name => "Host Master")
1265
- assert_not_nil user.name
1266
- same_user_in_different_thread = User.find(user.id)
1267
- same_user_in_different_thread.name = nil
1268
- same_user_in_different_thread.save!
1269
- assert_nil user.reload.name
1270
- end
1271
-
1272
- should "also remove foreign key attributes that are no longer in the database" do
1273
- user = User.create(:title => "Mr.", :name => "Host Master")
1274
- post = Post.create(:user => user)
1275
- assert_not_nil post.user_id
1276
- same_post_in_different_thread = Post.find(post.id)
1277
- same_post_in_different_thread.user = nil
1278
- same_post_in_different_thread.save!
1279
- assert_nil post.reload.user_id
1280
- end
1281
-
1282
- should "not be dirty after reloading" do
1283
- user = User.create(:title => "Mr.", :name => "Host Master")
1284
- user2 = User.find(user.id)
1285
- user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
1286
- user.reload
1287
- assert !user.dirty?
1288
- end
1289
-
1290
- should "ensure that association caches for has_many are cleared" do
1291
- user = User.create(:title => "Mr.", :name => "Host Master")
1292
- post = Post.create(:user => user)
1293
- assert_equal 1, user.posts.size
1294
- assert_not_nil user.instance_variable_get("@posts")
1295
- user.reload
1296
- assert_nil user.instance_variable_get("@posts")
1297
- assert_not_nil user.posts.first
1298
- end
1299
-
1300
- should "ensure that association caches for belongs_to are cleared" do
1301
- user = User.create(:title => "Mr.", :name => "Host Master")
1302
- post = Post.create(:user => user)
1303
- post.user
1304
- assert_not_nil post.instance_variable_get("@user")
1305
- post.reload
1306
- assert_nil post.instance_variable_get("@user")
1307
- assert_not_nil post.user
1308
- end
1309
-
1310
- should "update the revision" do
1311
- user = User.create(:title => "Mr.", :name => "Host Master")
1312
- user2 = User.find(user.id)
1313
- user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
1314
- user.reload
1315
- assert_equal user._rev, user2._rev
1316
- end
1317
- end
1318
-
1319
- context "with s3 interaction" do
1320
- setup do
1321
- CouchLogItem.instance_variable_set(:@_s3_connection, nil)
1322
- CouchLogItem._s3_options[:log_data][:ca_file] = nil
1323
-
1324
- bucket = stub(:bckt) do
1325
- stubs(:put).returns(true)
1326
- stubs(:get).returns(true)
1327
- end
1328
-
1329
- @bucket = bucket
1330
-
1331
- @s3 = stub(:s3) do
1332
- stubs(:bucket).returns(bucket)
1333
- end
1334
-
1335
- RightAws::S3.stubs(:new).returns @s3
1336
- @log_item = CouchLogItem.new
1337
- end
1338
-
1339
- context "when saving the attachment" do
1340
- should "fetch the collection" do
1341
- @log_item.log_data = "Yay! It logged!"
1342
- RightAws::S3.expects(:new).with('abcdef', 'secret!', :multi_thread => true, :ca_file => nil, :logger => nil).returns(@s3)
1343
- @log_item.save
1344
- end
1345
-
1346
- should "upload the file" do
1347
- @log_item.log_data = "Yay! It logged!"
1348
- @bucket.expects(:put).with(anything, "Yay! It logged!", {}, anything)
1349
- @log_item.save
1350
- end
1351
-
1352
- should "also upload on save!" do
1353
- @log_item.log_data = "Yay! It logged!"
1354
- @bucket.expects(:put).with(anything, "Yay! It logged!", {}, anything)
1355
- @log_item.save!
1356
- end
1357
-
1358
- should "use the specified bucket" do
1359
- @log_item.log_data = "Yay! It logged!"
1360
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1361
- @s3.expects(:bucket).with('mybucket').returns(@bucket)
1362
- @log_item.save
1363
- end
1364
-
1365
- should "create the bucket if it doesn't exist" do
1366
- @log_item.log_data = "Yay! log me"
1367
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1368
-
1369
- @s3.expects(:bucket).with('mybucket').returns(nil)
1370
- @s3.expects(:bucket).with('mybucket', true, 'private', :location => nil).returns(@bucket)
1371
- @log_item.save
1372
- end
1373
-
1374
- should "accept :us location option but not set it in RightAWS::S3" do
1375
- @log_item.log_data = "Yay! log me"
1376
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1377
- CouchLogItem._s3_options[:log_data][:location] = :us
1378
-
1379
- @s3.expects(:bucket).with('mybucket').returns(nil)
1380
- @s3.expects(:bucket).with('mybucket', true, 'private', :location => nil).returns(@bucket)
1381
- @log_item.save
1382
- end
1383
-
1384
- should "raise an error if the bucket is not ours" do
1385
- @log_item.log_data = "Yay! log me too"
1386
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1387
- CouchLogItem._s3_options[:log_data][:location] = :eu
1388
-
1389
- @s3.expects(:bucket).with('mybucket').returns(nil)
1390
- @s3.expects(:bucket).with('mybucket', true, 'private', :location => :eu).raises(RightAws::AwsError, 'BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again')
1391
-
1392
- assert_raise(ArgumentError) do
1393
- @log_item.save
1394
- end
1395
- end
1396
-
1397
- should "pass the logger object down to RightAws" do
1398
- logger = mock()
1399
- @log_item.log_data = "Yay! log me"
1400
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1401
- CouchLogItem._s3_options[:log_data][:logger] = logger
1402
-
1403
- RightAws::S3.expects(:new).with(anything, anything, {:logger => logger, :ca_file => nil, :multi_thread => true}).returns(@s3)
1404
- @log_item.save
1405
- end
1406
-
1407
- should "not upload the attachment when it hasn't been changed" do
1408
- @bucket.expects(:put).never
1409
- @log_item.save
1410
- end
1411
-
1412
- should "set the permissions to private by default" do
1413
- class Item
1414
- include SimplyStored::Couch
1415
- has_s3_attachment :log_data, :bucket => 'mybucket'
1416
- end
1417
- @bucket.expects(:put).with(anything, anything, {}, 'private')
1418
- @log_item = Item.new
1419
- @log_item.log_data = 'Yay!'
1420
- @log_item.save
1421
- end
1422
-
1423
- should "set the permissions to whatever's specified in the options for the attachment" do
1424
- @log_item.save
1425
- old_perms = CouchLogItem._s3_options[:log_data][:permissions]
1426
- CouchLogItem._s3_options[:log_data][:permissions] = 'public-read'
1427
- @bucket.expects(:put).with(anything, anything, {}, 'public-read')
1428
- @log_item.log_data = 'Yay!'
1429
- @log_item.save
1430
- CouchLogItem._s3_options[:log_data][:permissions] = old_perms
1431
- end
1432
-
1433
- should "use the full class name and the id as key" do
1434
- @log_item.save
1435
- @bucket.expects(:put).with("couch_log_items/log_data/#{@log_item.id}", 'Yay!', {}, anything)
1436
- @log_item.log_data = 'Yay!'
1437
- @log_item.save
1438
- end
1439
-
1440
- should "mark the attachment as not dirty after uploading" do
1441
- @log_item.log_data = 'Yay!'
1442
- @log_item.save
1443
- assert !@log_item.instance_variable_get(:@_s3_attachments)[:log_data][:dirty]
1444
- end
1445
-
1446
- should 'store the attachment when the validations succeeded' do
1447
- @log_item.log_data = 'Yay!'
1448
- @log_item.stubs(:valid?).returns(true)
1449
- @bucket.expects(:put)
1450
- @log_item.save
1451
- end
1452
-
1453
- should "not store the attachment when the validations failed" do
1454
- @log_item.log_data = 'Yay!'
1455
- @log_item.stubs(:valid?).returns(false)
1456
- @bucket.expects(:put).never
1457
- @log_item.save
1458
- end
1459
-
1460
- should "save the attachment status" do
1461
- @log_item.save
1462
- @log_item.attributes["log_data_attachments"]
1463
- end
1464
-
1465
- should "save generate the url for the attachment" do
1466
- @log_item._s3_options[:log_data][:bucket] = 'bucket-for-monsieur'
1467
- @log_item._s3_options[:log_data][:permissions] = 'public-read'
1468
- @log_item.save
1469
- assert_equal "http://bucket-for-monsieur.s3.amazonaws.com/#{@log_item.s3_attachment_key(:log_data)}", @log_item.log_data_url
1470
- end
1471
-
1472
- should "add a short-lived access key for private attachments" do
1473
- @log_item._s3_options[:log_data][:bucket] = 'bucket-for-monsieur'
1474
- @log_item._s3_options[:log_data][:location] = :us
1475
- @log_item._s3_options[:log_data][:permissions] = 'private'
1476
- @log_item.save
1477
- assert @log_item.log_data_url.include?("https://bucket-for-monsieur.s3.amazonaws.com:443/#{@log_item.s3_attachment_key(:log_data)}"), @log_item.log_data_url
1478
- assert @log_item.log_data_url.include?("Signature=")
1479
- assert @log_item.log_data_url.include?("Expires=")
1480
- end
1481
-
1482
- should "serialize data other than strings to json" do
1483
- @log_item.log_data = ['one log entry', 'and another one']
1484
- @bucket.expects(:put).with(anything, '["one log entry","and another one"]', {}, anything)
1485
- @log_item.save
1486
- end
1487
-
1488
- context "when noting the size of the attachment" do
1489
- should "store on upload" do
1490
- @log_item.log_data = 'abc'
1491
- @bucket.expects(:put)
1492
- assert @log_item.save
1493
- assert_equal 3, @log_item.log_data_size
1494
- end
1495
-
1496
- should "update the size if the attachment gets updated" do
1497
- @log_item.log_data = 'abc'
1498
- @bucket.stubs(:put)
1499
- assert @log_item.save
1500
- assert_equal 3, @log_item.log_data_size
1501
-
1502
- @log_item.log_data = 'example'
1503
- assert @log_item.save
1504
- assert_equal 7, @log_item.log_data_size
1505
- end
1506
-
1507
- should "store the size of json attachments" do
1508
- @log_item.log_data = ['abc']
1509
- @bucket.stubs(:put)
1510
- assert @log_item.save
1511
- assert_equal ['abc'].to_json.size, @log_item.log_data_size
1512
- end
1513
- end
1514
- end
1515
-
1516
- context "when fetching the data" do
1517
- should "create a configured S3 connection" do
1518
- CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
1519
- CouchLogItem._s3_options[:log_data][:location] = :eu
1520
- CouchLogItem._s3_options[:log_data][:ca_file] = '/etc/ssl/ca.crt'
1521
-
1522
- RightAws::S3.expects(:new).with('abcdef', 'secret!', :multi_thread => true, :ca_file => '/etc/ssl/ca.crt', :logger => nil).returns(@s3)
1523
-
1524
- @log_item.log_data
1525
- end
1526
-
1527
- should "fetch the data from s3 and set the attachment attribute" do
1528
- @log_item.instance_variable_set(:@_s3_attachments, {})
1529
- @bucket.expects(:get).with("couch_log_items/log_data/#{@log_item.id}").returns("Yay!")
1530
- assert_equal "Yay!", @log_item.log_data
1531
- end
1532
-
1533
- should "not mark the the attachment as dirty" do
1534
- @log_item.instance_variable_set(:@_s3_attachments, {})
1535
- @bucket.expects(:get).with("couch_log_items/log_data/#{@log_item.id}").returns("Yay!")
1536
- @log_item.log_data
1537
- assert !@log_item._s3_attachments[:log_data][:dirty]
1538
- end
1539
-
1540
- should "not try to fetch the attachment if the value is already set" do
1541
- @log_item.log_data = "Yay!"
1542
- @bucket.expects(:get).never
1543
- assert_equal "Yay!", @log_item.log_data
1544
- end
1545
- end
1546
-
1547
- context "when deleting" do
1548
- setup do
1549
- CouchLogItem._s3_options[:log_data][:after_delete] = :nothing
1550
- @log_item.log_data = 'Yatzzee'
1551
- @log_item.save
1552
- end
1553
-
1554
- should "do nothing to S3" do
1555
- @bucket.expects(:key).never
1556
- @log_item.delete
1557
- end
1558
-
1559
- should "also delete on S3 if configured so" do
1560
- CouchLogItem._s3_options[:log_data][:after_delete] = :delete
1561
- s3_key = mock(:delete => true)
1562
- @bucket.expects(:key).with(@log_item.s3_attachment_key('log_data'), true).returns(s3_key)
1563
- @log_item.delete
1564
- end
1565
-
1566
- end
1567
- end
1568
-
1569
- context "when using soft deletable" do
1570
- should "know when it is enabled" do
1571
- assert Hemorrhoid.soft_deleting_enabled?
1572
- assert !User.soft_deleting_enabled?
1573
- end
1574
-
1575
- should "define a :deleted_at attribute" do
1576
- h = Hemorrhoid.new
1577
- assert h.respond_to?(:deleted_at)
1578
- assert h.respond_to?(:deleted_at=)
1579
- assert_equal :deleted_at, Hemorrhoid.soft_delete_attribute
1580
- end
1581
-
1582
- should "define a hard delete methods" do
1583
- h = Hemorrhoid.new
1584
- assert h.respond_to?(:destroy!)
1585
- assert h.respond_to?(:delete!)
1586
- end
1587
-
1588
- context "when deleting" do
1589
- setup do
1590
- @user = User.new(:name => 'BigT', :title => 'Dr.')
1591
- @user.save!
1592
- @hemorrhoid = Hemorrhoid.new
1593
- @hemorrhoid.user = @user
1594
- @hemorrhoid.save!
1595
- end
1596
-
1597
- should "not delete the object but populate the soft_delete_attribute" do
1598
- now = Time.now
1599
- Time.stubs(:now).returns(now)
1600
- assert_nil @hemorrhoid.deleted_at
1601
- assert @hemorrhoid.delete
1602
- assert_equal now, @hemorrhoid.deleted_at
1603
- end
1604
-
1605
- should "survive reloads with the new attribute" do
1606
- assert_nil @hemorrhoid.deleted_at
1607
- assert @hemorrhoid.delete
1608
- @hemorrhoid.reload
1609
- assert_not_nil @hemorrhoid.deleted_at
1610
- end
1611
-
1612
- should "know when it is deleted" do
1613
- assert !@hemorrhoid.deleted?
1614
- @hemorrhoid.delete
1615
- assert @hemorrhoid.deleted?
1616
- end
1617
-
1618
- should "not consider objects without soft-deleted as deleted" do
1619
- assert !@user.deleted?
1620
- @user.delete
1621
- assert !@user.deleted?
1622
- end
1623
-
1624
- should "not delete in DB" do
1625
- CouchPotato.database.expects(:destroy_document).never
1626
- @hemorrhoid.destroy
1627
- end
1628
-
1629
- should "really delete if asked to" do
1630
- CouchPotato.database.expects(:destroy_document).with(@hemorrhoid)
1631
- @hemorrhoid.destroy!
1632
- end
1633
-
1634
- context "callbacks" do
1635
-
1636
- should "still fire the callbacks" do
1637
- @hemorrhoid = Hemorrhoid.create
1638
- $before = nil
1639
- $after = nil
1640
- def @hemorrhoid.before_destroy_callback
1641
- $before = "now"
1642
- end
1643
-
1644
- def @hemorrhoid.after_destroy_callback
1645
- $after = "now"
1646
- end
1647
-
1648
- @hemorrhoid.destroy
1649
-
1650
- assert_not_nil $before
1651
- assert_not_nil $after
1652
- end
1653
-
1654
- should "not fire the callbacks on the real destroy if the object is already deleted" do
1655
- @hemorrhoid = Hemorrhoid.create
1656
- def @hemorrhoid.before_destroy_callback
1657
- raise "Callback called even though #{skip_callbacks.inspect}"
1658
- end
1659
-
1660
- def @hemorrhoid.after_destroy_callback
1661
- raise "Callback called even though #{skip_callbacks.inspect}"
1662
- end
1663
-
1664
- def @hemorrhoid.deleted?
1665
- true
1666
- end
1667
-
1668
- assert_nothing_raised do
1669
- @hemorrhoid.destroy!
1670
- end
1671
- end
1672
-
1673
- should "not fire the callbacks on the real destroy if the object is not deleted" do
1674
- @hemorrhoid = Hemorrhoid.create
1675
- $before = nil
1676
- $after = nil
1677
- def @hemorrhoid.before_destroy_callback
1678
- $before = "now"
1679
- end
1680
-
1681
- def @hemorrhoid.after_destroy_callback
1682
- $after = "now"
1683
- end
1684
-
1685
- @hemorrhoid.destroy!
1686
-
1687
- assert_not_nil $before
1688
- assert_not_nil $after
1689
- end
1690
- end
1691
-
1692
- context "when handling the dependent objects" do
1693
- setup do
1694
- @sub = SubHemorrhoid.new
1695
- @sub.hemorrhoid = @hemorrhoid
1696
- @sub.save!
1697
-
1698
- @easy_sub = EasySubHemorrhoid.new
1699
- @easy_sub.hemorrhoid = @hemorrhoid
1700
- @easy_sub.save!
1701
-
1702
- @rash = Rash.new
1703
- @rash.hemorrhoid = @hemorrhoid
1704
- @rash.save!
1705
-
1706
- @hemorrhoid.reload
1707
- end
1708
-
1709
- should "delete them" do
1710
- @hemorrhoid.delete
1711
- @sub.reload
1712
- assert @sub.deleted?
1713
- assert_raise(SimplyStored::RecordNotFound) do
1714
- EasySubHemorrhoid.find(@easy_sub.id, :with_deleted => true)
1715
- end
1716
- @rash = Rash.find(@rash.id)
1717
- assert_nil @rash.hemorrhoid_id
1718
- end
1719
-
1720
- should "really delete them if the parent is really deleted" do
1721
- @hemorrhoid.delete!
1722
- assert_raise(SimplyStored::RecordNotFound) do
1723
- EasySubHemorrhoid.find(@sub.id, :with_deleted => true)
1724
- end
1725
-
1726
- assert_raise(SimplyStored::RecordNotFound) do
1727
- EasySubHemorrhoid.find(@easy_sub.id, :with_deleted => true)
1728
- end
1729
-
1730
- @rash = Rash.find(@rash.id)
1731
- assert_nil @rash.hemorrhoid_id
1732
- end
1733
-
1734
- should "not nullify dependents if they are soft-deletable" do
1735
- small_rash = SmallRash.create(:hemorrhoid => @hemorrhoid)
1736
- @hemorrhoid.reload
1737
- @hemorrhoid.destroy
1738
- small_rash = SmallRash.find(small_rash.id)
1739
- assert_not_nil small_rash.hemorrhoid_id
1740
- assert_equal @hemorrhoid.id, small_rash.hemorrhoid_id
1741
- end
1742
- end
1743
-
1744
- end
1745
-
1746
- context "when loading" do
1747
- setup do
1748
- @user = User.new(:name => 'BigT', :title => 'Dr.')
1749
- @user.save!
1750
- @hemorrhoid = Hemorrhoid.new
1751
- @hemorrhoid.user = @user
1752
- @hemorrhoid.save!
1753
- end
1754
-
1755
- context "by id" do
1756
- should "not be found by default" do
1757
- @hemorrhoid.destroy
1758
- assert_raise(SimplyStored::RecordNotFound) do
1759
- Hemorrhoid.find(@hemorrhoid.id)
1760
- end
1761
- end
1762
-
1763
- should "be found if supplied with :with_deleted" do
1764
- @hemorrhoid.destroy
1765
-
1766
- assert_not_nil Hemorrhoid.find(@hemorrhoid.id, :with_deleted => true)
1767
- end
1768
-
1769
- should "not be found if it is really gone" do
1770
- old_id = @hemorrhoid.id
1771
- @hemorrhoid.destroy!
1772
-
1773
- assert_raise(SimplyStored::RecordNotFound) do
1774
- Hemorrhoid.find(old_id)
1775
- end
1776
- end
1777
-
1778
- should "always reload" do
1779
- @hemorrhoid.destroy
1780
- assert_nothing_raised do
1781
- @hemorrhoid.reload
1782
- end
1783
- assert_not_nil @hemorrhoid.deleted_at
1784
- end
1785
- end
1786
-
1787
- context "all" do
1788
- setup do
1789
- recreate_db
1790
- @hemorrhoid = Hemorrhoid.create
1791
- assert @hemorrhoid.destroy
1792
- assert @hemorrhoid.reload.deleted?
1793
- end
1794
-
1795
- should "not load deleted" do
1796
- assert_equal [], Hemorrhoid.find(:all)
1797
- assert_equal [], Hemorrhoid.find(:all, :with_deleted => false)
1798
- end
1799
-
1800
- should "load non-deleted" do
1801
- hemorrhoid = Hemorrhoid.create
1802
- assert_not_equal [], Hemorrhoid.find(:all)
1803
- assert_not_equal [], Hemorrhoid.find(:all, :with_deleted => false)
1804
- end
1805
-
1806
- should "load deleted if asked to" do
1807
- assert_equal [@hemorrhoid.id], Hemorrhoid.find(:all, :with_deleted => true).map(&:id)
1808
- end
1809
- end
1810
-
1811
- context "first" do
1812
- setup do
1813
- recreate_db
1814
- @hemorrhoid = Hemorrhoid.create
1815
- assert @hemorrhoid.destroy
1816
- assert @hemorrhoid.reload.deleted?
1817
- end
1818
-
1819
- should "not load deleted" do
1820
- assert_nil Hemorrhoid.find(:first)
1821
- assert_nil Hemorrhoid.find(:first, :with_deleted => false)
1822
- end
1823
-
1824
- should "load non-deleted" do
1825
- hemorrhoid = Hemorrhoid.create
1826
- assert_not_nil Hemorrhoid.find(:first)
1827
- assert_not_nil Hemorrhoid.find(:first, :with_deleted => false)
1828
- end
1829
-
1830
- should "load deleted if asked to" do
1831
- assert_equal @hemorrhoid, Hemorrhoid.find(:first, :with_deleted => true)
1832
- end
1833
- end
1834
-
1835
- context "find_by and find_all_by" do
1836
- setup do
1837
- recreate_db
1838
- @hemorrhoid = Hemorrhoid.create(:nickname => 'Claas', :size => 3)
1839
- @hemorrhoid.destroy
1840
- end
1841
-
1842
- context "find_by" do
1843
- should "not load deleted" do
1844
- assert_nil Hemorrhoid.find_by_nickname('Claas')
1845
- assert_nil Hemorrhoid.find_by_nickname('Claas', :with_deleted => false)
1846
-
1847
- assert_nil Hemorrhoid.find_by_nickname_and_size('Claas', 3)
1848
- assert_nil Hemorrhoid.find_by_nickname_and_size('Claas', 3, :with_deleted => false)
1849
- end
1850
-
1851
- should "load non-deleted" do
1852
- hemorrhoid = Hemorrhoid.create(:nickname => 'OtherNick', :size => 3)
1853
- assert_equal hemorrhoid.id, Hemorrhoid.find_by_nickname('OtherNick', :with_deleted => true).id
1854
- assert_equal hemorrhoid.id, Hemorrhoid.find_by_nickname('OtherNick').id
1855
- end
1856
-
1857
- should "load deleted if asked to" do
1858
- assert_not_nil Hemorrhoid.find_by_nickname('Claas', :with_deleted => true)
1859
- assert_equal @hemorrhoid.id, Hemorrhoid.find_by_nickname('Claas', :with_deleted => true).id
1860
-
1861
- assert_not_nil Hemorrhoid.find_by_nickname_and_size('Claas', 3, :with_deleted => true)
1862
- assert_equal @hemorrhoid.id, Hemorrhoid.find_by_nickname_and_size('Claas', 3, :with_deleted => true).id
1863
- end
1864
- end
1865
-
1866
- context "find_all_by" do
1867
- should "not load deleted" do
1868
- assert_equal [], Hemorrhoid.find_all_by_nickname('Claas')
1869
- assert_equal [], Hemorrhoid.find_all_by_nickname('Claas', :with_deleted => false)
1870
-
1871
- assert_equal [], Hemorrhoid.find_all_by_nickname_and_size('Claas', 3)
1872
- assert_equal [], Hemorrhoid.find_all_by_nickname_and_size('Claas', 3, :with_deleted => false)
1873
- end
1874
-
1875
- should "load non-deleted" do
1876
- hemorrhoid = Hemorrhoid.create(:nickname => 'Lampe', :size => 4)
1877
- assert_equal [hemorrhoid.id], Hemorrhoid.find_all_by_nickname('Lampe').map(&:id)
1878
- end
1879
-
1880
- should "load deleted if asked to" do
1881
- assert_equal [@hemorrhoid.id], Hemorrhoid.find_all_by_nickname('Claas', :with_deleted => true).map(&:id)
1882
- assert_equal [@hemorrhoid.id], Hemorrhoid.find_all_by_nickname_and_size('Claas', 3, :with_deleted => true).map(&:id)
1883
- end
1884
- end
1885
-
1886
- should "reuse the same view - when find_all_by is called first" do
1887
- assert_equal [], Hemorrhoid.find_all_by_nickname('Claas')
1888
- assert_nil Hemorrhoid.find_by_nickname('Claas')
1889
- end
1890
-
1891
- should "reuse the same view - when find_by is called first" do
1892
- assert_nil Hemorrhoid.find_by_nickname('Claas')
1893
- assert_equal [], Hemorrhoid.find_all_by_nickname('Claas')
1894
- end
1895
- end
1896
-
1897
- context "by relation" do
1898
- setup do
1899
- @hemorrhoid.destroy
1900
- end
1901
-
1902
- context "has_many" do
1903
- should "not load deleted by default" do
1904
- assert_equal [], @user.hemorrhoids
1905
- end
1906
-
1907
- should "load deleted if asked to" do
1908
- assert_equal [@hemorrhoid.id], @user.hemorrhoids(:with_deleted => true).map(&:id)
1909
- end
1910
- end
1911
-
1912
- context "has_many :through" do
1913
- setup do
1914
- @user = User.create(:name => 'BigT', :title => 'Dr.')
1915
- @pain = Pain.create
1916
-
1917
- @hemorrhoid = Hemorrhoid.new
1918
- @hemorrhoid.user = @user
1919
- @hemorrhoid.pain = @pain
1920
- @hemorrhoid.save!
1921
-
1922
- @hemorrhoid.destroy
1923
- end
1924
-
1925
- should "not load deleted by default" do
1926
- assert_equal [], @user.pains
1927
- end
1928
-
1929
- should "load deleted if asked to" do
1930
- assert_equal [@pain.id], @user.pains(:with_deleted => true).map(&:id)
1931
- end
1932
- end
1933
-
1934
- context "has_one" do
1935
- setup do
1936
- @spot = Spot.create
1937
-
1938
- @hemorrhoid = Hemorrhoid.new
1939
- @hemorrhoid.spot = @spot
1940
- @hemorrhoid.save!
1941
-
1942
- @hemorrhoid.destroy
1943
- end
1944
-
1945
- should "not load deleted by default" do
1946
- assert_nil @spot.hemorrhoid
1947
- end
1948
-
1949
- should "load deleted if asked to" do
1950
- assert_equal @hemorrhoid.id, @spot.hemorrhoid(:with_deleted => true).id
1951
- end
1952
- end
1953
-
1954
- context "belongs_to" do
1955
- setup do
1956
- @hemorrhoid = Hemorrhoid.new
1957
- @hemorrhoid.save!
1958
-
1959
- @sub = SubHemorrhoid.new
1960
- @sub.hemorrhoid = @hemorrhoid
1961
- @sub.save!
1962
-
1963
- @hemorrhoid.destroy
1964
- end
1965
-
1966
- should "not load deleted by default" do
1967
- @sub.reload
1968
- assert_raise(SimplyStored::RecordNotFound) do
1969
- assert_nil @sub.hemorrhoid
1970
- end
1971
- end
1972
-
1973
- should "load deleted if asked to" do
1974
- @sub.reload
1975
- assert_equal @hemorrhoid.id, @sub.hemorrhoid(:with_deleted => true).id
1976
- end
1977
- end
1978
-
1979
- end
1980
-
1981
- end
1982
-
1983
- context "when counting" do
1984
- setup do
1985
- @hemorrhoid = Hemorrhoid.create(:nickname => 'Claas')
1986
- assert @hemorrhoid.destroy
1987
- assert @hemorrhoid.reload.deleted?
1988
- end
1989
-
1990
- should "not count deleted" do
1991
- assert_equal 0, Hemorrhoid.count
1992
- assert_equal 0, Hemorrhoid.count(:with_deleted => false)
1993
- end
1994
-
1995
- should "count non-deleted" do
1996
- hemorrhoid = Hemorrhoid.create(:nickname => 'Claas')
1997
- assert_equal 1, Hemorrhoid.count
1998
- assert_equal 1, Hemorrhoid.count(:with_deleted => false)
1999
- end
2000
-
2001
- should "count deleted if asked to" do
2002
- assert_equal 1, Hemorrhoid.count(:with_deleted => true)
2003
- end
2004
-
2005
- context "count_by" do
2006
- should "not count deleted" do
2007
- assert_equal 0, Hemorrhoid.count_by_nickname('Claas')
2008
- assert_equal 0, Hemorrhoid.count_by_nickname('Claas', :with_deleted => false)
2009
- end
2010
-
2011
- should "count deleted if asked to" do
2012
- assert_equal 1, Hemorrhoid.count_by_nickname('Claas', :with_deleted => true)
2013
- end
2014
- end
2015
- end
2016
-
2017
- end
2018
-
2019
- context "when handling conflicts" do
2020
- setup do
2021
- @original = User.create(:name => 'Mickey Mouse', :title => "Dr.", :homepage => 'www.gmx.de')
2022
- @copy = User.find(@original.id)
2023
- User.auto_conflict_resolution_on_save = true
2024
- end
2025
-
2026
- should "be able to save without modifications" do
2027
- assert @copy.save
2028
- end
2029
-
2030
- should "be able to save when modification happen on different attributes" do
2031
- @original.name = "Pluto"
2032
- assert @original.save
2033
-
2034
- @copy.title = 'Prof.'
2035
- assert_nothing_raised do
2036
- assert @copy.save
2037
- end
2038
-
2039
- assert_equal "Pluto", @copy.reload.name
2040
- assert_equal "Prof.", @copy.reload.title
2041
- assert_equal "www.gmx.de", @copy.reload.homepage
2042
- end
2043
-
2044
- should "be able to save when modification happen on different, multiple attributes - remote" do
2045
- @original.name = "Pluto"
2046
- @original.homepage = 'www.google.com'
2047
- assert @original.save
2048
-
2049
- @copy.title = 'Prof.'
2050
- assert_nothing_raised do
2051
- assert @copy.save
2052
- end
2053
-
2054
- assert_equal "Pluto", @copy.reload.name
2055
- assert_equal "Prof.", @copy.reload.title
2056
- assert_equal "www.google.com", @copy.reload.homepage
2057
- end
2058
-
2059
- should "be able to save when modification happen on different, multiple attributes locally" do
2060
- @original.name = "Pluto"
2061
- assert @original.save
2062
-
2063
- @copy.title = 'Prof.'
2064
- @copy.homepage = 'www.google.com'
2065
- assert_nothing_raised do
2066
- assert @copy.save
2067
- end
2068
-
2069
- assert_equal "Pluto", @copy.reload.name
2070
- assert_equal "Prof.", @copy.reload.title
2071
- assert_equal "www.google.com", @copy.reload.homepage
2072
- end
2073
-
2074
- should "re-raise the conflict if there is no merge possible" do
2075
- @original.name = "Pluto"
2076
- assert @original.save
2077
-
2078
- @copy.name = 'Prof.'
2079
- assert_raise(RestClient::Conflict) do
2080
- assert @copy.save
2081
- end
2082
-
2083
- assert_equal "Prof.", @copy.name
2084
- assert_equal "Pluto", @copy.reload.name
2085
- end
2086
-
2087
- should "re-raise the conflict if retried several times" do
2088
- exception = RestClient::Conflict.new
2089
- CouchPotato.database.expects(:save_document).raises(exception).times(3)
2090
-
2091
- @copy.name = 'Prof.'
2092
- assert_raise(RestClient::Conflict) do
2093
- assert @copy.save
2094
- end
2095
- end
2096
-
2097
- should "not try to merge and re-save if auto_conflict_resolution_on_save is disabled" do
2098
- User.auto_conflict_resolution_on_save = false
2099
- exception = RestClient::Conflict.new
2100
- CouchPotato.database.expects(:save_document).raises(exception).times(1)
2101
-
2102
- @copy.name = 'Prof.'
2103
- assert_raise(RestClient::Conflict) do
2104
- assert @copy.save
2105
- end
2106
- end
2107
-
2108
- end
2109
-
2110
- end
2111
- end