cohitre-relaxdb 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/spec_models.rb'
3
+
4
+ describe RelaxDB::HasOneProxy do
5
+
6
+ before(:all) do
7
+ RelaxDB.configure(:host => "localhost", :port => 5984)
8
+ end
9
+
10
+ before(:each) do
11
+ RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
12
+ RelaxDB.use_db "relaxdb_spec_db"
13
+ end
14
+
15
+ describe "has_one" do
16
+
17
+ it "should return nil when accessed before assignment" do
18
+ p = Photo.new
19
+ p.rating.should == nil
20
+ end
21
+
22
+ it "should be establishable via a constructor attribute" do
23
+ r = Rating.new
24
+ p = Photo.new :rating => r
25
+ p.rating.should == r
26
+ end
27
+
28
+ it "should be establishable via assignment" do
29
+ p = Photo.new
30
+ r = Rating.new
31
+ p.rating = r
32
+ p.rating.should == r
33
+ end
34
+
35
+ it "should return the same object on repeated invocations" do
36
+ p = Photo.new.save
37
+ p.rating = Rating.new
38
+ p = RelaxDB.load(p._id)
39
+ p.rating.object_id.should == p.rating.object_id
40
+ end
41
+
42
+ it "should be preserved across load / save boundary" do
43
+ r = Rating.new
44
+ p = Photo.new(:rating => r).save
45
+ p = RelaxDB.load p._id
46
+ p.rating.should == r
47
+ end
48
+
49
+ it "should be able reference itself via its child" do
50
+ r = Rating.new
51
+ p = Photo.new(:rating => r).save
52
+ p = RelaxDB.load p._id
53
+ p.rating.photo.should == p
54
+ end
55
+
56
+ it "should work with MultiWordClassNames" do
57
+ c = MultiWordChild.new
58
+ m = MultiWordClass.new(:multi_word_child => c).save
59
+ m = RelaxDB.load m._id
60
+ m.multi_word_child.should == c
61
+ end
62
+
63
+ describe "#=" do
64
+
65
+ it "should create a reference from the child to the parent" do
66
+ p = Photo.new
67
+ r = Rating.new
68
+ p.rating = r
69
+ r.photo.should == p
70
+ end
71
+
72
+ it "should save the assigned object" do
73
+ p = Photo.new
74
+ r = Rating.new
75
+ p.rating = r
76
+ r.should_not be_unsaved
77
+ end
78
+
79
+ it "will not save the parent" do
80
+ p = Photo.new
81
+ r = Rating.new
82
+ p.rating = r
83
+ p.should be_unsaved
84
+ end
85
+
86
+ it "should set the target to nil when nil is assigned" do
87
+ p = Photo.new
88
+ p.rating = nil
89
+ p.rating.should be_nil
90
+ end
91
+
92
+ it "should nullify any existing relationship in the database" do
93
+ p = Photo.new
94
+ r = Rating.new
95
+ p.rating = r
96
+ p.rating = nil
97
+ RelaxDB.load(r._id).photo.should be_nil
98
+ end
99
+
100
+ it "should nullify any existing relationship on a known in-memory object" do
101
+ p = Photo.new
102
+ r = Rating.new
103
+ p.rating = r
104
+ p.rating = nil
105
+ r.photo.should be_nil
106
+ end
107
+
108
+ it "will not nullify any existing relationship on unknown in-memory objects" do
109
+ p = Photo.new.save
110
+ r = Rating.new
111
+ p.rating = r
112
+ r_copy = RelaxDB.load(r._id)
113
+ p.rating = nil
114
+ r_copy.photo.should_not be_nil
115
+ end
116
+
117
+ it "will not throw an error when the rhs fails validation" do
118
+ d = Dysfunctional.new.save
119
+ f = Failure.new
120
+ d.failure = f
121
+ d.failure.should == f
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/spec_models.rb'
3
+
4
+ describe RelaxDB::Query do
5
+
6
+ describe "#view_name" do
7
+
8
+ it "should match a single key attribute" do
9
+ q = RelaxDB::SortedByView.new("", :foo)
10
+ q.view_name.should == "all_sorted_by_foo"
11
+ end
12
+
13
+ it "should match key attributes" do
14
+ q = RelaxDB::SortedByView.new("", :foo, :bar)
15
+ q.view_name.should == "all_sorted_by_foo_and_bar"
16
+ end
17
+ end
18
+
19
+ describe "#view_path" do
20
+
21
+ it "should list design document and view name" do
22
+ q = RelaxDB::Query.new("Zenith", "mount")
23
+ q.view_path.should == "_view/Zenith/mount"
24
+ end
25
+
26
+ it "should contain URL and JSON encoded key when the key has been set" do
27
+ q = RelaxDB::Query.new("", "")
28
+ q.key("olympus")
29
+ q.view_path.should == "_view//?key=%22olympus%22"
30
+ end
31
+
32
+ it "should honour startkey, endkey and count" do
33
+ q = RelaxDB::Query.new("", "")
34
+ q.startkey(["olympus"]).endkey(["vesuvius", 3600]).count(100)
35
+ q.view_path.should == "_view//?startkey=%5B%22olympus%22%5D&endkey=%5B%22vesuvius%22%2C3600%5D&count=100"
36
+ end
37
+
38
+ it "should specify a null key if key was set to nil" do
39
+ q = RelaxDB::Query.new("", "")
40
+ q.key(nil)
41
+ q.view_path.should == "_view//?key=null"
42
+ end
43
+
44
+ it "should specify a null startkey if startkey was set to nil" do
45
+ q = RelaxDB::Query.new("", "")
46
+ q.startkey(nil)
47
+ q.view_path.should == "_view//?startkey=null"
48
+ end
49
+
50
+ it "should specify a null endkey if endkey was set to nil" do
51
+ q = RelaxDB::Query.new("", "")
52
+ q.endkey(nil)
53
+ q.view_path.should == "_view//?endkey=null"
54
+ end
55
+
56
+ it "should not JSON encode the startkey_docid" do
57
+ q = RelaxDB::Query.new("", "")
58
+ q.startkey_docid("foo")
59
+ q.view_path.should == "_view//?startkey_docid=foo"
60
+ end
61
+
62
+ it "should not JSON encode the endkey_docid" do
63
+ q = RelaxDB::Query.new("", "")
64
+ q.endkey_docid("foo")
65
+ q.view_path.should == "_view//?endkey_docid=foo"
66
+ end
67
+
68
+ end
69
+
70
+ describe "#keys" do
71
+
72
+ it "should return a JSON encoded hash" do
73
+ q = RelaxDB::Query.new("", "")
74
+ q.keys(["a", "b"])
75
+ q.keys.should == '{"keys":["a","b"]}'
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,141 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/spec_models.rb'
3
+
4
+ describe RelaxDB::ReferencesManyProxy do
5
+
6
+ before(:all) do
7
+ RelaxDB.configure(:host => "localhost", :port => 5984)
8
+ end
9
+
10
+ before(:each) do
11
+ RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
12
+ RelaxDB.use_db "relaxdb_spec_db"
13
+ end
14
+
15
+ describe "references_many" do
16
+
17
+ it "is now deprecated and will be removed in the near future" do
18
+ end
19
+
20
+ it "should preserve the relationships across the save / load boundary" do
21
+ p = Photo.new
22
+ t = Tag.new
23
+ t.photos << p
24
+
25
+ p = RelaxDB.load p._id
26
+ p.tags.size.should == 1
27
+ p.tags[0].should == t
28
+
29
+ t = RelaxDB.load t._id
30
+ t.photos.size.should == 1
31
+ t.photos[0].should == p
32
+ end
33
+
34
+ describe "#=" do
35
+ it "should not be invoked" do
36
+ end
37
+ end
38
+
39
+ describe "#<<" do
40
+
41
+ it "should set the relationship on both sides" do
42
+ p = Photo.new(:name => "photo")
43
+ t = Tag.new(:name => "tag")
44
+ p.tags << t
45
+
46
+ p.tags.size.should == 1
47
+ p.tags[0].name.should == "tag"
48
+
49
+ t.photos.size.should == 1
50
+ t.photos[0].name.should == "photo"
51
+ end
52
+
53
+ it "should not create duplicates when the same object is added more than once" do
54
+ p = Photo.new
55
+ t = Tag.new
56
+ p.tags << t << t
57
+ p.tags.size.should == 1
58
+ end
59
+
60
+ it "should not create duplicates when reciprocal objects are added from opposite sides" do
61
+ p = Photo.new
62
+ t = Tag.new
63
+ p.tags << t
64
+ t.photos << p
65
+ p.tags.size.should == 1
66
+ t.photos.size.should == 1
67
+ end
68
+
69
+ end
70
+
71
+ describe "#delete" do
72
+
73
+ it "should nullify relationship on both sides" do
74
+ p = Photo.new
75
+ t = Tag.new
76
+ p.tags << t
77
+
78
+ p.tags.delete(t)
79
+ p.tags.should be_empty
80
+ t.photos.should be_empty
81
+ end
82
+
83
+ end
84
+
85
+ describe "owner#destroy" do
86
+
87
+ it "will not remove its membership from its peers in memory" do
88
+ # Documentating behaviour, not stating that this behaviour is desired
89
+ p = Photo.new
90
+ t = Tag.new
91
+ p.tags << t
92
+
93
+ p.destroy!
94
+ t.photos.size.should == 1
95
+ end
96
+
97
+ it "should remove its membership from its peers in CouchDB" do
98
+ p = Photo.new
99
+ t = Tag.new
100
+ p.tags << t
101
+
102
+ p.destroy!
103
+ RelaxDB.load(t._id).photos.should be_empty
104
+ end
105
+
106
+ end
107
+
108
+ # Leaving this test as a reminder of problems with all.destroy and a self referential
109
+ # references_many until references_many is removed
110
+ #
111
+ # This test more complex than it needs to be to prove the point
112
+ # It also serves as a proof of a self referential references_many, but there are better places for that
113
+ # it "all.destroy should play nice with self referential references_many" do
114
+ # u1 = TwitterUser.new(:name => "u1")
115
+ # u2 = TwitterUser.new(:name => "u2")
116
+ # u3 = TwitterUser.new(:name => "u3")
117
+ #
118
+ # u1.followers << u2
119
+ # u1.followers << u3
120
+ # u3.leaders << u2
121
+ #
122
+ # u1f = u1.followers.map { |u| u.name }
123
+ # u1f.sort.should == ["u2", "u3"]
124
+ # u1.leaders.should be_empty
125
+ #
126
+ # u2.leaders.size.should == 1
127
+ # u2.leaders[0].name.should == "u1"
128
+ # u2.followers.size.should == 1
129
+ # u2.followers[0].name.should == "u3"
130
+ #
131
+ # u3l = u3.leaders.map { |u| u.name }
132
+ # u3l.sort.should == ["u1", "u2"]
133
+ # u3.followers.should be_empty
134
+ #
135
+ # TwitterUser.all.destroy!
136
+ # TwitterUser.all.should be_empty
137
+ # end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,137 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/spec_models.rb'
3
+
4
+ describe RelaxDB do
5
+
6
+ before(:all) do
7
+ RelaxDB.configure(:host => "localhost", :port => 5984)
8
+ end
9
+
10
+ before(:each) do
11
+ RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
12
+ RelaxDB.use_db "relaxdb_spec_db"
13
+ end
14
+
15
+ describe ".create_object" do
16
+
17
+ it "should return an instance of a known object if passed a hash with a class key" do
18
+ data = { "class" => "Item" }
19
+ obj = RelaxDB.create_object(data)
20
+ obj.should be_instance_of(Item)
21
+ end
22
+
23
+ it "should return an instance of a dynamically created object if no class key is provided" do
24
+ data = { "name" => "tesla coil", "strength" => 5000 }
25
+ obj = RelaxDB.create_object(data)
26
+ obj.name.should == "tesla coil"
27
+ obj.strength.should == 5000
28
+ end
29
+
30
+ end
31
+
32
+ describe ".bulk_save" do
33
+
34
+ it "should be invokable multiple times" do
35
+ t1 = Tag.new(:name => "t1")
36
+ t2 = Tag.new(:name => "t2")
37
+ RelaxDB.bulk_save(t1, t2)
38
+ RelaxDB.bulk_save(t1, t2)
39
+ end
40
+
41
+ it "should succeed when passed no args" do
42
+ RelaxDB.bulk_save
43
+ end
44
+
45
+ end
46
+
47
+ describe ".replicate_db" do
48
+
49
+ it "should replicate the named database" do
50
+ orig = "relaxdb_spec_db"
51
+ replica = "relaxdb_spec_db_replica"
52
+ RelaxDB.delete_db replica rescue "ok"
53
+ Atom.new.save # implicitly saved to orig
54
+ RelaxDB.replicate_db orig, replica
55
+ RelaxDB.use_db replica
56
+ Atom.all.size.should == 1
57
+ end
58
+
59
+ end
60
+
61
+ describe ".load" do
62
+
63
+ it "should load a single document" do
64
+ a = Atom.new.save
65
+ ar = RelaxDB.load a._id
66
+ ar.should == a
67
+ end
68
+
69
+ it "should load an arbitrary number of documents" do
70
+ a1, a2 = Atom.new.save, Atom.new.save
71
+ ar1, ar2 = RelaxDB.load a1._id, a2._id
72
+ ar1.should == a1
73
+ ar2.should == a2
74
+ end
75
+
76
+ end
77
+
78
+ describe ".view" do
79
+
80
+ map_func = %Q<
81
+ function (doc) {
82
+ emit(doc._id, doc);
83
+ }
84
+ >
85
+
86
+ it "should request a view and return a hash" do
87
+ RelaxDB::DesignDocument.get("viewtest").add_view("simple", "map", map_func).save
88
+ data = RelaxDB.view("viewtest", "simple")
89
+ data.should be_instance_of(Hash)
90
+ end
91
+
92
+ it "may accept a block" do
93
+ RelaxDB::DesignDocument.get("viewtest").add_view("simple", "map", map_func).save
94
+ RelaxDB.db.put("x", {}.to_json)
95
+ RelaxDB.db.put("y", {}.to_json)
96
+ data = RelaxDB.view("viewtest", "simple") { |q| q.key("x") }
97
+ data["rows"].size.should == 1
98
+ end
99
+
100
+ it "should be queryable with a multi key post" do
101
+ 5.times { |i| Primitives.new(:num => i).save }
102
+ # Create the view
103
+ Primitives.all.sorted_by(:num)
104
+ resp = RelaxDB.view("Primitives", "all_sorted_by_num") do |q|
105
+ q.keys([0, 4])
106
+ q.reduce(false).group(true) # group invocation should hopefully be temporary
107
+ end
108
+ RelaxDB.instantiate(resp).map{ |p| p.num }.should == [0, 4]
109
+ end
110
+
111
+ end
112
+
113
+ describe ".merge" do
114
+
115
+ it "should merge rows sharing a common merge key into a single ViewObject" do
116
+ rows = [
117
+ {"value" => {"sculptor_id" => 1, "sculpture_name" => "strandbeesten"} },
118
+ {"value" => {"sculptor_id" => 1, "sculptor_name" => "hans"} },
119
+ {"value" => {"sculptor_id" => 2, "sculpture_name" => "parading dogs"} },
120
+ {"value" => {"sculptor_id" => 2, "sculptor_name" => "holmes"} }
121
+ ]
122
+ data = {"rows" => rows}
123
+ result = RelaxDB.merge(data, "sculptor_id")
124
+ result = result.sort { |a, b| a.sculptor_name <=> b.sculptor_name }
125
+
126
+ result[0].sculptor_name.should == "hans"
127
+ result[0].sculpture_name.should == "strandbeesten"
128
+ result[1].sculptor_name.should == "holmes"
129
+ result[1].sculpture_name.should == "parading dogs"
130
+ end
131
+
132
+ end
133
+
134
+ # if caching is added
135
+ # it "should offer an example where behaviour is different with caching enabled and caching disabled"
136
+
137
+ end