simply_stored 0.3.6 → 0.3.7

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.
@@ -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