djsun-mongomapper 0.3.1.1 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/History +20 -1
  2. data/Rakefile +5 -3
  3. data/VERSION +1 -1
  4. data/lib/mongomapper/associations/base.rb +3 -5
  5. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +5 -3
  6. data/lib/mongomapper/associations/belongs_to_proxy.rb +4 -4
  7. data/lib/mongomapper/associations/many_documents_proxy.rb +32 -14
  8. data/lib/mongomapper/associations/proxy.rb +2 -6
  9. data/lib/mongomapper/associations.rb +38 -15
  10. data/lib/mongomapper/document.rb +165 -95
  11. data/lib/mongomapper/dynamic_finder.rb +38 -0
  12. data/lib/mongomapper/embedded_document.rb +116 -88
  13. data/lib/mongomapper/finder_options.rb +3 -14
  14. data/lib/mongomapper/key.rb +12 -16
  15. data/lib/mongomapper/serializers/json_serializer.rb +15 -12
  16. data/lib/mongomapper/support.rb +30 -0
  17. data/lib/mongomapper.rb +7 -33
  18. data/mongomapper.gemspec +10 -7
  19. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +14 -0
  20. data/test/functional/associations/test_belongs_to_proxy.rb +10 -0
  21. data/test/functional/associations/test_many_polymorphic_proxy.rb +46 -52
  22. data/test/functional/associations/test_many_proxy.rb +71 -12
  23. data/test/functional/test_associations.rb +9 -2
  24. data/test/functional/test_document.rb +281 -20
  25. data/test/functional/test_rails_compatibility.rb +2 -3
  26. data/test/models.rb +39 -8
  27. data/test/unit/serializers/test_json_serializer.rb +46 -12
  28. data/test/unit/test_association_base.rb +10 -2
  29. data/test/unit/test_document.rb +7 -9
  30. data/test/unit/test_embedded_document.rb +180 -24
  31. data/test/unit/test_finder_options.rb +7 -38
  32. data/test/unit/test_key.rb +54 -24
  33. metadata +5 -5
  34. data/test/unit/test_mongo_id.rb +0 -35
@@ -15,6 +15,38 @@ class DocumentTest < Test::Unit::TestCase
15
15
  @document.collection.clear
16
16
  end
17
17
 
18
+ context "Saving a document with a custom id" do
19
+ should "clear custom id flag when saved" do
20
+ doc = @document.new(:id => '1234')
21
+ doc.using_custom_id?.should be_true
22
+ doc.save.should be_true
23
+ doc.using_custom_id?.should be_false
24
+ end
25
+ end
26
+
27
+ context "Loading a document from the database with keys that are not defined" do
28
+ setup do
29
+ @id = XGen::Mongo::Driver::ObjectID.new.to_s
30
+ @document.collection.insert({
31
+ :_id => @id,
32
+ :first_name => 'John',
33
+ :last_name => 'Nunemaker',
34
+ :age => 27,
35
+ :favorite_color => 'red',
36
+ :skills => ['ruby', 'rails', 'javascript', 'xhtml', 'css']
37
+ })
38
+ end
39
+
40
+ should "assign all keys from database" do
41
+ doc = @document.find(@id)
42
+ doc.first_name.should == 'John'
43
+ doc.last_name.should == 'Nunemaker'
44
+ doc.age.should == 27
45
+ doc.favorite_color.should == 'red'
46
+ doc.skills.should == ['ruby', 'rails', 'javascript', 'xhtml', 'css']
47
+ end
48
+ end
49
+
18
50
  context "Document Class Methods" do
19
51
  context "Using key with type Array" do
20
52
  setup do
@@ -53,7 +85,7 @@ class DocumentTest < Test::Unit::TestCase
53
85
  doc.tags.should == ["foo"]
54
86
  end
55
87
 
56
- should_eventually "work with << then save" do
88
+ should "work with << then save" do
57
89
  doc = @document.new
58
90
  doc.tags << "foo"
59
91
  doc.tags << "bar"
@@ -61,7 +93,6 @@ class DocumentTest < Test::Unit::TestCase
61
93
  doc.tags.should == %w(foo bar)
62
94
  @document.find(doc.id).tags.should == %w(foo bar)
63
95
  end
64
-
65
96
  end
66
97
 
67
98
  context "Using key with type Hash" do
@@ -73,14 +104,14 @@ class DocumentTest < Test::Unit::TestCase
73
104
  doc = @document.new
74
105
  doc.foo.should == {}
75
106
  end
76
-
107
+
77
108
  should "work with []=" do
78
109
  doc = @document.new
79
110
  doc.foo["quux"] = "bar"
80
111
  doc.foo["quux"].should == "bar"
81
112
  doc.foo.should == { "quux" => "bar" }
82
113
  end
83
-
114
+
84
115
  should "work with indifferent access" do
85
116
  doc = @document.new
86
117
  doc.foo = {:baz => 'bar'}
@@ -92,6 +123,7 @@ class DocumentTest < Test::Unit::TestCase
92
123
  doc = @document.new
93
124
  doc.foo = {:baz => 'bar'}
94
125
  doc.save
126
+
95
127
  doc = @document.find(doc.id)
96
128
  doc.foo[:baz].should == 'bar'
97
129
  doc.foo['baz'].should == 'bar'
@@ -132,6 +164,10 @@ class DocumentTest < Test::Unit::TestCase
132
164
  @doc_instance.id.size.should == 24
133
165
  end
134
166
 
167
+ should "no longer be new?" do
168
+ @doc_instance.new?.should be_false
169
+ end
170
+
135
171
  should "return instance of document" do
136
172
  @doc_instance.should be_instance_of(@document)
137
173
  @doc_instance.first_name.should == 'John'
@@ -249,11 +285,7 @@ class DocumentTest < Test::Unit::TestCase
249
285
  end
250
286
 
251
287
  should "raise error if document not found" do
252
- lambda { @document.find(MongoID.new) }.should raise_error(MongoMapper::DocumentNotFound)
253
- end
254
-
255
- should_eventually "raise error if id is illegal" do
256
- lambda { @document.find(1) }.should raise_error(MongoMapper::IllegalID)
288
+ lambda { @document.find(123) }.should raise_error(MongoMapper::DocumentNotFound)
257
289
  end
258
290
  end
259
291
 
@@ -280,7 +312,7 @@ class DocumentTest < Test::Unit::TestCase
280
312
  context "with #all" do
281
313
  should "find all documents based on criteria" do
282
314
  @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
283
- @document.all(:conditions => {:last_name => 'Nunemaker'}).should == [@doc1, @doc3]
315
+ @document.all(:conditions => {:last_name => 'Nunemaker'}, :order => 'age desc').should == [@doc1, @doc3]
284
316
  end
285
317
  end
286
318
 
@@ -299,17 +331,75 @@ class DocumentTest < Test::Unit::TestCase
299
331
 
300
332
  context "with :last" do
301
333
  should "find last document" do
302
- @document.find(:last).should == @doc3
334
+ @document.find(:last, :order => 'age').should == @doc2
303
335
  end
304
336
  end
305
337
 
306
338
  context "with #last" do
307
339
  should "find last document based on criteria" do
308
- @document.last.should == @doc3
340
+ @document.last(:order => 'age').should == @doc2
309
341
  @document.last(:conditions => {:age => 28}).should == @doc2
310
342
  end
311
343
  end
312
344
 
345
+ context "with :find_by" do
346
+ should "find document based on argument" do
347
+ @document.find_by_first_name('John').should == @doc1
348
+ @document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
349
+ @document.find_by_age(27).should == @doc1
350
+ end
351
+
352
+ should "not raise error" do
353
+ @document.find_by_first_name('Mongo').should be_nil
354
+ end
355
+
356
+ should "define a method for each key" do
357
+ @document.methods(false).select { |e| e =~ /^find_by_/ }.size == @document.keys.size
358
+ end
359
+ end
360
+
361
+ context "with dynamic finders" do
362
+ should "find document based on all arguments" do
363
+ @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
364
+ end
365
+
366
+ should "not find the document if an argument is wrong" do
367
+ @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 28).should be_nil
368
+ end
369
+
370
+ should "find all documents based on arguments" do
371
+ docs = @document.find_all_by_last_name('Nunemaker')
372
+ docs.should be_kind_of(Array)
373
+ docs.should include(@doc1)
374
+ docs.should include(@doc3)
375
+ end
376
+
377
+ should "find last document based on arguments" do
378
+ doc = @document.find_last_by_last_name('Nunemaker', :order => 'age')
379
+ doc.should == @doc1
380
+ end
381
+
382
+ should "initialize document with given arguments" do
383
+ doc = @document.find_or_initialize_by_first_name_and_last_name('David', 'Cuadrado')
384
+ doc.should be_new
385
+ doc.first_name.should == 'David'
386
+ end
387
+
388
+ should "not initialize document if document is found" do
389
+ doc = @document.find_or_initialize_by_first_name('John')
390
+ doc.should_not be_new
391
+ end
392
+
393
+ should "create document with given arguments" do
394
+ doc = @document.find_or_create_by_first_name_and_last_name('David', 'Cuadrado')
395
+ doc.should_not be_new
396
+ doc.first_name.should == 'David'
397
+ end
398
+
399
+ should "raise error if document is not found" do
400
+ lambda {@document.find_by_first_name_and_last_name!(1,2)}.should raise_error(MongoMapper::DocumentNotFound)
401
+ end
402
+ end
313
403
  end # finding documents
314
404
 
315
405
  context "Finding document by id" do
@@ -324,7 +414,7 @@ class DocumentTest < Test::Unit::TestCase
324
414
  end
325
415
 
326
416
  should "return nil if document not found" do
327
- @document.find_by_id(MongoID.new).should be(nil)
417
+ @document.find_by_id(1234).should be(nil)
328
418
  end
329
419
  end
330
420
 
@@ -448,6 +538,123 @@ class DocumentTest < Test::Unit::TestCase
448
538
  end
449
539
  end
450
540
 
541
+ context ":dependent" do
542
+ setup do
543
+ # FIXME: make use of already defined models
544
+ class ::Property
545
+ include MongoMapper::Document
546
+ end
547
+ Property.delete_all
548
+
549
+ class ::Thing
550
+ include MongoMapper::Document
551
+ key :name, String
552
+ end
553
+ Thing.delete_all
554
+ end
555
+
556
+ teardown do
557
+ Object.send :remove_const, 'Property' if defined?(::Property)
558
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
559
+ end
560
+
561
+ context "many" do
562
+ context "=> destroy" do
563
+ setup do
564
+ Property.key :thing_id, String
565
+ Property.belongs_to :thing, :dependent => :destroy
566
+ Thing.many :properties, :dependent => :destroy
567
+
568
+ @thing = Thing.create(:name => "Tree")
569
+ @property1 = Property.create
570
+ @property2 = Property.create
571
+ @property3 = Property.create
572
+ @thing.properties << @property1
573
+ @thing.properties << @property2
574
+ @thing.properties << @property3
575
+ end
576
+
577
+ should "should destroy the associated documents" do
578
+ @thing.properties.count.should == 3
579
+ @thing.destroy
580
+ @thing.properties.count.should == 0
581
+ Property.count.should == 0
582
+ end
583
+ end
584
+
585
+ context "=> delete_all" do
586
+ setup do
587
+ Property.key :thing_id, String
588
+ Property.belongs_to :thing
589
+ Thing.has_many :properties, :dependent => :delete_all
590
+
591
+ @thing = Thing.create(:name => "Tree")
592
+ @property1 = Property.create
593
+ @property2 = Property.create
594
+ @property3 = Property.create
595
+ @thing.properties << @property1
596
+ @thing.properties << @property2
597
+ @thing.properties << @property3
598
+ end
599
+
600
+ should "should delete associated documents" do
601
+ @thing.properties.count.should == 3
602
+ @thing.destroy
603
+ @thing.properties.count.should == 0
604
+ Property.count.should == 0
605
+ end
606
+ end
607
+
608
+ context "=> nullify" do
609
+ setup do
610
+ Property.key :thing_id, String
611
+ Property.belongs_to :thing
612
+ Thing.has_many :properties, :dependent => :nullify
613
+
614
+ @thing = Thing.create(:name => "Tree")
615
+ @property1 = Property.create
616
+ @property2 = Property.create
617
+ @property3 = Property.create
618
+ @thing.properties << @property1
619
+ @thing.properties << @property2
620
+ @thing.properties << @property3
621
+ end
622
+
623
+ should "should nullify relationship but not destroy associated documents" do
624
+ @thing.properties.count.should == 3
625
+ @thing.destroy
626
+ @thing.properties.count.should == 0
627
+ Property.count.should == 3
628
+ end
629
+ end
630
+ end
631
+
632
+ context "belongs_to" do
633
+ context "=> destroy" do
634
+ setup do
635
+ Property.key :thing_id, String
636
+ Property.belongs_to :thing, :dependent => :destroy
637
+ Thing.has_many :properties
638
+
639
+ @thing = Thing.create(:name => "Tree")
640
+ @property1 = Property.create
641
+ @property2 = Property.create
642
+ @property3 = Property.create
643
+ @thing.properties << @property1
644
+ @thing.properties << @property2
645
+ @thing.properties << @property3
646
+ end
647
+
648
+ should "destroy the thing" do
649
+ Thing.count.should == 1
650
+ @property1.destroy
651
+ Thing.count.should == 0
652
+ @property1.thing.should be_frozen
653
+ end
654
+ end
655
+ end
656
+ end
657
+
451
658
  context "Counting documents in collection" do
452
659
  setup do
453
660
  @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
@@ -504,13 +711,13 @@ class DocumentTest < Test::Unit::TestCase
504
711
  @document.ensure_index :first_name, :unique => true
505
712
  end
506
713
 
507
- should_eventually "allow creating index on multiple keys" do
714
+ should "allow creating index on multiple keys" do
508
715
  index_name = nil
509
716
  lambda {
510
717
  index_name = @document.ensure_index [[:first_name, 1], [:last_name, -1]]
511
718
  }.should change { @document.collection.index_information.size }.by(1)
512
719
 
513
- index_name.should == 'first_name_1_last_name_-1'
720
+ [ 'first_name_1_last_name_-1', 'last_name_-1_first_name_1' ].should include(index_name)
514
721
 
515
722
  index = @document.collection.index_information[index_name]
516
723
  index.should_not be_nil
@@ -551,6 +758,21 @@ class DocumentTest < Test::Unit::TestCase
551
758
  from_db.first_name.should == 'John'
552
759
  from_db.age.should == 27
553
760
  end
761
+
762
+ should "allow to add custom attributes to the document" do
763
+ @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
764
+ @doc.save
765
+ from_db = @document.find(@doc.id)
766
+ from_db.gender.should == 'male'
767
+ from_db.tags.should == [1, "2"]
768
+ end
769
+
770
+ should "allow to use custom methods to assign properties" do
771
+ person = RealPerson.new(:realname => "David")
772
+ person.save
773
+ from_db = RealPerson.find(person.id)
774
+ from_db.name.should == "David"
775
+ end
554
776
  end
555
777
 
556
778
  context "Saving an existing document" do
@@ -575,6 +797,14 @@ class DocumentTest < Test::Unit::TestCase
575
797
  from_db.first_name.should == 'Johnny'
576
798
  from_db.age.should == 30
577
799
  end
800
+
801
+ should "allow to update custom attributes" do
802
+ @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
803
+ @doc.gender = 'Male'
804
+ @doc.save
805
+ from_db = @document.find(@doc.id)
806
+ from_db.gender.should == 'Male'
807
+ end
578
808
  end
579
809
 
580
810
  context "Calling update attributes on a new document" do
@@ -603,6 +833,12 @@ class DocumentTest < Test::Unit::TestCase
603
833
  from_db.first_name.should == 'Johnny'
604
834
  from_db.age.should == 30
605
835
  end
836
+
837
+ should "allow to update custom attributes" do
838
+ @doc.update_attributes(:gender => 'mALe')
839
+ from_db = @document.find(@doc.id)
840
+ from_db.gender.should == 'mALe'
841
+ end
606
842
  end
607
843
 
608
844
  context "Updating an existing document using update attributes" do
@@ -626,6 +862,20 @@ class DocumentTest < Test::Unit::TestCase
626
862
  from_db.age.should == 30
627
863
  end
628
864
  end
865
+
866
+ context "update_attributes" do
867
+ setup do
868
+ @document.key :foo, String, :required => true
869
+ end
870
+
871
+ should "return true if document valid" do
872
+ @document.new.update_attributes(:foo => 'bar').should be_true
873
+ end
874
+
875
+ should "return false if document not valid" do
876
+ @document.new.update_attributes({}).should be_false
877
+ end
878
+ end
629
879
 
630
880
  context "Destroying a document that exists" do
631
881
  setup do
@@ -640,6 +890,10 @@ class DocumentTest < Test::Unit::TestCase
640
890
  should "raise error if assignment is attempted" do
641
891
  lambda { @doc.first_name = 'Foo' }.should raise_error(TypeError)
642
892
  end
893
+
894
+ should "do nothing if destroy is called again" do
895
+ @doc.destroy.should be_false
896
+ end
643
897
  end
644
898
 
645
899
  context "Destroying a document that is a new" do
@@ -660,6 +914,10 @@ class DocumentTest < Test::Unit::TestCase
660
914
  end
661
915
 
662
916
  context "timestamping" do
917
+ setup do
918
+ @document.timestamps!
919
+ end
920
+
663
921
  should "set created_at and updated_at on create" do
664
922
  doc = @document.new(:first_name => 'John', :age => 27)
665
923
  doc.created_at.should be(nil)
@@ -679,13 +937,16 @@ class DocumentTest < Test::Unit::TestCase
679
937
  doc.updated_at.should_not == old_updated_at
680
938
  end
681
939
 
682
- should_eventually "set updated_at on document update but leave created_at alone" do
940
+ should "set updated_at on document update but leave created_at alone" do
683
941
  doc = @document.create(:first_name => 'John', :age => 27)
684
942
  old_created_at = doc.created_at
685
943
  old_updated_at = doc.updated_at
686
- doc = @document.update(old._id, { :first_name => 'Johnny' })
687
- doc.created_at.should == old_created_at
688
- doc.updated_at.should_not == old_updated_at
944
+ sleep 1 # this annoys me
945
+ @document.update(doc._id, { :first_name => 'Johnny' })
946
+
947
+ from_db = @document.find(doc.id)
948
+ from_db.created_at.to_i.should == old_created_at.to_i
949
+ from_db.updated_at.to_i.should_not == old_updated_at.to_i
689
950
  end
690
951
  end
691
- end
952
+ end
@@ -18,9 +18,8 @@ class TestRailsCompatibility < Test::Unit::TestCase
18
18
  end
19
19
 
20
20
  should "have to_param that returns id" do
21
- id = MongoID.new
22
- instance = Order.create('_id' => id.to_s)
23
- instance.to_param.should == id.to_s
21
+ instance = Order.create('_id' => 1234)
22
+ instance.to_param.should == '1234'
24
23
  end
25
24
 
26
25
  should "alias new to new_record?" do
data/test/models.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  class Address
2
2
  include MongoMapper::EmbeddedDocument
3
+
3
4
  key :address, String
4
5
  key :city, String
5
6
  key :state, String
@@ -8,7 +9,12 @@ end
8
9
 
9
10
  class Message
10
11
  include MongoMapper::Document
12
+
11
13
  key :body, String
14
+ key :position, Integer
15
+ key :_type, String
16
+ key :room_id, String
17
+
12
18
  belongs_to :room
13
19
  end
14
20
 
@@ -18,12 +24,14 @@ class Chat < Message; end
18
24
 
19
25
  class Room
20
26
  include MongoMapper::Document
27
+
21
28
  key :name, String
22
29
  many :messages, :polymorphic => true
23
30
  end
24
31
 
25
32
  class Project
26
33
  include MongoMapper::Document
34
+
27
35
  key :name, String
28
36
  many :statuses
29
37
  many :addresses
@@ -31,32 +39,48 @@ end
31
39
 
32
40
  class Status
33
41
  include MongoMapper::Document
42
+
43
+ key :project_id, String
44
+ key :target_id, String
45
+ key :target_type, String
46
+ key :name, String
47
+ key :position, Integer
48
+
34
49
  belongs_to :project
35
50
  belongs_to :target, :polymorphic => true
36
- key :name, String
37
51
  end
38
52
 
39
53
  class RealPerson
40
54
  include MongoMapper::Document
41
- many :pets
55
+
56
+ many :pets
42
57
  key :name, String
58
+
59
+ def realname=(n)
60
+ self.name = n
61
+ end
43
62
  end
44
63
 
45
64
  class Person
46
65
  include MongoMapper::EmbeddedDocument
66
+
47
67
  key :name, String
48
68
  key :child, Person
69
+
49
70
  many :pets
50
71
  end
51
72
 
52
73
  class Pet
53
74
  include MongoMapper::EmbeddedDocument
75
+
54
76
  key :name, String
55
77
  key :species, String
56
78
  end
57
79
 
58
80
  class Media
59
81
  include MongoMapper::EmbeddedDocument
82
+
83
+ key :_type, String
60
84
  key :file, String
61
85
  end
62
86
 
@@ -75,34 +99,41 @@ end
75
99
 
76
100
  class Catalog
77
101
  include MongoMapper::Document
102
+
78
103
  many :medias, :polymorphic => true
79
104
  end
80
105
 
81
106
  module TrModels
82
107
  class Transport
83
108
  include MongoMapper::EmbeddedDocument
109
+
110
+ key :_type, String
84
111
  key :license_plate, String
85
112
  end
86
-
113
+
87
114
  class Car < TrModels::Transport
88
115
  include MongoMapper::EmbeddedDocument
116
+
89
117
  key :model, String
90
118
  key :year, Integer
91
119
  end
92
-
120
+
93
121
  class Bus < TrModels::Transport
94
122
  include MongoMapper::EmbeddedDocument
123
+
95
124
  key :max_passengers, Integer
96
125
  end
97
-
126
+
98
127
  class Ambulance < TrModels::Transport
99
128
  include MongoMapper::EmbeddedDocument
129
+
100
130
  key :icu, Boolean
101
131
  end
102
-
132
+
103
133
  class Fleet
104
134
  include MongoMapper::Document
135
+
105
136
  many :transports, :polymorphic => true, :class_name => "TrModels::Transport"
106
- key :name, String
137
+ key :name, String
107
138
  end
108
- end
139
+ end
@@ -51,7 +51,7 @@ class JsonSerializationTest < Test::Unit::TestCase
51
51
  should "allow attribute filtering with except" do
52
52
  json = @contact.to_json(:except => [:name, :age])
53
53
 
54
- assert_match %r{"_id"}, json
54
+ assert_no_match %r{"_id"}, json
55
55
  assert_no_match %r{"name"}, json
56
56
  assert_no_match %r{"age"}, json
57
57
  assert_match %r{"awesome"}, json
@@ -59,26 +59,60 @@ class JsonSerializationTest < Test::Unit::TestCase
59
59
  assert_match %r{"preferences"}, json
60
60
  end
61
61
 
62
- context "including methods" do
62
+ context "_id key" do
63
+ should "not be included by default" do
64
+ json = @contact.to_json
65
+ assert_no_match %r{"_id":}, json
66
+ end
67
+
68
+ should "not be included even if :except is used" do
69
+ json = @contact.to_json(:except => :name)
70
+ assert_no_match %r{"_id":}, json
71
+ end
72
+ end
73
+
74
+ context "id method" do
63
75
  setup do
64
76
  def @contact.label; "Has cheezburger"; end
65
77
  def @contact.favorite_quote; "Constraints are liberating"; end
66
78
  end
67
79
 
68
- should "include label method" do
80
+ should "be included by default" do
81
+ json = @contact.to_json
82
+ assert_match %r{"id"}, json
83
+ end
84
+
85
+ should "be included when single method included" do
69
86
  json = @contact.to_json(:methods => :label)
87
+ assert_match %r{"id"}, json
70
88
  assert_match %r{"label":"Has cheezburger"}, json
89
+ assert_match %r{"name":"Konata Izumi"}, json
90
+ assert_no_match %r{"favorite_quote":"Constraints are liberating"}, json
71
91
  end
72
92
 
73
- should "include name and label method" do
74
- json = @contact.to_json(:only => :name, :methods => :label)
75
-
93
+ should "be included when multiple methods included" do
94
+ json = @contact.to_json(:methods => [:label, :favorite_quote])
95
+ assert_match %r{"id"}, json
76
96
  assert_match %r{"label":"Has cheezburger"}, json
97
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, json
77
98
  assert_match %r{"name":"Konata Izumi"}, json
78
- assert_no_match %r{"age":16}, json
79
- assert_no_match %r{"awesome"}, json
80
- assert_no_match %r{"created_at"}, json
81
- assert_no_match %r{"preferences"}, json
99
+ end
100
+
101
+ should "not be included if :only is present" do
102
+ json = @contact.to_json(:only => :name)
103
+ assert_no_match %r{"id":}, json
104
+ end
105
+ end
106
+
107
+ context "including methods" do
108
+ setup do
109
+ def @contact.label; "Has cheezburger"; end
110
+ def @contact.favorite_quote; "Constraints are liberating"; end
111
+ end
112
+
113
+ should "include single method" do
114
+ json = @contact.to_json(:methods => :label)
115
+ assert_match %r{"label":"Has cheezburger"}, json
82
116
  end
83
117
 
84
118
  should "include multiple methods" do
@@ -106,8 +140,8 @@ class JsonSerializationTest < Test::Unit::TestCase
106
140
  end
107
141
 
108
142
  should "allow attribute filtering with except" do
109
- json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at, :updated_at, :_id])
110
- assert_equal %([{"id":"","age":39},{"id":"","age":14}]), json
143
+ json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at, :updated_at])
144
+ assert_equal %([{"id":null,"age":39},{"id":null,"age":14}]), json
111
145
  end
112
146
  end
113
147
 
@@ -78,8 +78,16 @@ class AssociationBaseTest < Test::Unit::TestCase
78
78
  end
79
79
  end
80
80
 
81
- should "have belongs_to_key_name" do
82
- Base.new(:belongs_to, :foo).belongs_to_key_name.should == 'foo_id'
81
+ context "foreign_key" do
82
+ should "default to assocation_name_id" do
83
+ base = Base.new(:belongs_to, :foo)
84
+ base.foreign_key.should == 'foo_id'
85
+ end
86
+
87
+ should "be overridable with :foreign_key option" do
88
+ base = Base.new(:belongs_to, :foo, :foreign_key => 'foobar_id')
89
+ base.foreign_key.should == 'foobar_id'
90
+ end
83
91
  end
84
92
 
85
93
  should "have ivar that is association name" do