cohitre-relaxdb 0.2.2

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