tripod 0.0.10 → 0.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.
- data/README.md +11 -5
- data/lib/tripod.rb +3 -0
- data/lib/tripod/attributes.rb +49 -57
- data/lib/tripod/components.rb +2 -0
- data/lib/tripod/errors.rb +1 -0
- data/lib/tripod/errors/field_not_present.rb +8 -0
- data/lib/tripod/fields.rb +4 -31
- data/lib/tripod/finders.rb +19 -12
- data/lib/tripod/persistence.rb +12 -0
- data/lib/tripod/predicates.rb +78 -0
- data/lib/tripod/repository.rb +20 -3
- data/lib/tripod/resource.rb +23 -24
- data/lib/tripod/serialization.rb +27 -0
- data/lib/tripod/sparql_client.rb +15 -4
- data/lib/tripod/version.rb +1 -1
- data/spec/app/models/person.rb +4 -0
- data/spec/tripod/attributes_spec.rb +79 -70
- data/spec/tripod/fields_spec.rb +15 -65
- data/spec/tripod/finders_spec.rb +14 -19
- data/spec/tripod/persistence_spec.rb +62 -58
- data/spec/tripod/predicates_spec.rb +82 -0
- data/spec/tripod/repository_spec.rb +53 -26
- data/spec/tripod/resource_spec.rb +20 -40
- data/spec/tripod/serialization_spec.rb +36 -0
- data/spec/tripod/state_spec.rb +2 -2
- data/tripod.gemspec +3 -2
- metadata +38 -20
data/spec/tripod/finders_spec.rb
CHANGED
@@ -18,8 +18,8 @@ describe Tripod::Finders do
|
|
18
18
|
stmt.object = RDF::URI.new('http://bill')
|
19
19
|
stmts << stmt
|
20
20
|
|
21
|
-
r = Person.new(@ric_uri
|
22
|
-
r.hydrate!(stmts)
|
21
|
+
r = Person.new(@ric_uri)
|
22
|
+
r.hydrate!(:graph => stmts)
|
23
23
|
r.save
|
24
24
|
r
|
25
25
|
end
|
@@ -32,8 +32,8 @@ describe Tripod::Finders do
|
|
32
32
|
stmt.predicate = RDF::URI.new('http://name')
|
33
33
|
stmt.object = "bill"
|
34
34
|
stmts << stmt
|
35
|
-
b = Person.new(@bill_uri
|
36
|
-
b.hydrate!(stmts)
|
35
|
+
b = Person.new(@bill_uri)
|
36
|
+
b.hydrate!(:graph => stmts)
|
37
37
|
b.save
|
38
38
|
b
|
39
39
|
end
|
@@ -41,38 +41,33 @@ describe Tripod::Finders do
|
|
41
41
|
describe '.find' do
|
42
42
|
|
43
43
|
context 'when record exists' do
|
44
|
-
|
45
|
-
it 'does not error' do
|
46
|
-
r = Person.find(ric.uri)
|
47
|
-
end
|
44
|
+
let(:person) { Person.find(ric.uri) }
|
48
45
|
|
49
46
|
it 'hydrates and return an object' do
|
50
|
-
|
51
|
-
|
52
|
-
r['http://knows'].should == [RDF::URI.new('http://bill')]
|
47
|
+
person.name.should == "ric"
|
48
|
+
person.knows.should == [RDF::URI('http://bill')]
|
53
49
|
end
|
54
50
|
|
55
51
|
it 'sets the graph on the instantiated object' do
|
56
|
-
|
57
|
-
|
58
|
-
r.graph_uri.should == RDF::URI("http://people")
|
52
|
+
person.graph_uri.should_not be_nil
|
53
|
+
person.graph_uri.should == RDF::URI("http://graph")
|
59
54
|
end
|
60
55
|
|
61
56
|
it "returns a non-new record" do
|
62
|
-
|
63
|
-
r.new_record?.should be_false
|
57
|
+
person.new_record?.should be_false
|
64
58
|
end
|
65
59
|
|
66
60
|
end
|
67
61
|
|
68
62
|
context 'when record does not exist' do
|
69
63
|
it 'raises not found' do
|
70
|
-
lambda { Person.find('http://
|
64
|
+
lambda { Person.find('http://nonexistent') }.should raise_error(Tripod::Errors::ResourceNotFound)
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
68
|
+
context 'with a given graph URI' do
|
74
69
|
|
75
|
-
|
70
|
+
end
|
76
71
|
end
|
77
72
|
|
78
73
|
describe '.where' do
|
@@ -90,7 +85,7 @@ describe Tripod::Finders do
|
|
90
85
|
res.last.should == bill
|
91
86
|
|
92
87
|
res.first.name.should == "ric"
|
93
|
-
res.first
|
88
|
+
res.first.knows.should == [RDF::URI.new("http://bill")]
|
94
89
|
end
|
95
90
|
|
96
91
|
it 'uses the uri and graph variables if supplied' do
|
@@ -4,14 +4,15 @@ describe Tripod::Persistence do
|
|
4
4
|
|
5
5
|
let(:unsaved_person) do
|
6
6
|
@unsaved_uri = @uri = 'http://uri'
|
7
|
-
@
|
7
|
+
@graph_uri = 'http://graph'
|
8
|
+
@graph1 = RDF::Graph.new(@graph_uri)
|
8
9
|
stmt = RDF::Statement.new
|
9
10
|
stmt.subject = RDF::URI.new(@uri)
|
10
11
|
stmt.predicate = RDF::URI.new('http://pred')
|
11
12
|
stmt.object = RDF::URI.new('http://obj')
|
12
13
|
@graph1 << stmt
|
13
14
|
p = Person.new(@uri, 'http://graph')
|
14
|
-
p.hydrate!(@graph1)
|
15
|
+
p.hydrate!(:graph => @graph1)
|
15
16
|
p
|
16
17
|
end
|
17
18
|
|
@@ -24,65 +25,38 @@ describe Tripod::Persistence do
|
|
24
25
|
stmt.object = RDF::URI.new('http://obj2')
|
25
26
|
@graph2 << stmt
|
26
27
|
p = Person.new(@uri2, 'http://graph')
|
27
|
-
p.hydrate!(@graph2)
|
28
|
+
p.hydrate!(:graph => @graph2)
|
28
29
|
p.save
|
29
30
|
p
|
30
31
|
end
|
31
32
|
|
32
33
|
|
33
|
-
describe "
|
34
|
+
describe ".save" do
|
35
|
+
it 'saves the contents to the db' do
|
36
|
+
unsaved_person.save.should be_true
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'uri not set' do
|
47
|
-
it 'should not succeed' do
|
48
|
-
unsaved_person.uri = nil
|
49
|
-
unsaved_person.save.should be_false
|
50
|
-
unsaved_person.should_not be_valid
|
51
|
-
unsaved_person.errors.should_not be_empty
|
52
|
-
unsaved_person.errors[:uri].length.should ==1
|
53
|
-
unsaved_person.errors[:uri].should == ["can't be blank"]
|
54
|
-
end
|
38
|
+
# try reading the data back out.
|
39
|
+
p2 = Person.new(@uri)
|
40
|
+
p2.hydrate!
|
41
|
+
repo_statements = p2.repository.statements
|
42
|
+
repo_statements.count.should == 1
|
43
|
+
repo_statements.first.subject.should == RDF::URI.new(@uri)
|
44
|
+
repo_statements.first.predicate.should == RDF::URI.new('http://pred')
|
45
|
+
repo_statements.first.object.should == RDF::URI.new('http://obj')
|
55
46
|
end
|
56
47
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
unsaved_person.save.should be_true
|
61
|
-
|
62
|
-
# try reading the data back out.
|
63
|
-
p2 = Person.new(@uri)
|
64
|
-
p2.hydrate!
|
65
|
-
repo_statements = p2.repository.statements
|
66
|
-
repo_statements.count.should == 1
|
67
|
-
repo_statements.first.subject.should == RDF::URI.new(@uri)
|
68
|
-
repo_statements.first.predicate.should == RDF::URI.new('http://pred')
|
69
|
-
repo_statements.first.object.should == RDF::URI.new('http://obj')
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should leave other people untouched' do
|
73
|
-
# save the unsaved person
|
74
|
-
unsaved_person.save.should be_true
|
75
|
-
|
76
|
-
# read the saved person back out the db, and check he's untouched.
|
77
|
-
p2 = Person.new(saved_person.uri)
|
78
|
-
p2.hydrate!
|
79
|
-
p2.repository.dump(:ntriples).should == saved_person.repository.dump(:ntriples)
|
80
|
-
end
|
48
|
+
it 'should leave other people untouched' do
|
49
|
+
# save the unsaved person
|
50
|
+
unsaved_person.save.should be_true
|
81
51
|
|
52
|
+
# read the saved person back out the db, and check he's untouched.
|
53
|
+
p2 = Person.new(saved_person.uri)
|
54
|
+
p2.hydrate!
|
55
|
+
p2.repository.dump(:ntriples).should == saved_person.repository.dump(:ntriples)
|
82
56
|
end
|
83
57
|
end
|
84
58
|
|
85
|
-
describe "
|
59
|
+
describe ".destroy" do
|
86
60
|
|
87
61
|
it 'removes all triples from the db' do
|
88
62
|
saved_person.destroy.should be_true
|
@@ -95,42 +69,72 @@ describe Tripod::Persistence do
|
|
95
69
|
|
96
70
|
end
|
97
71
|
|
98
|
-
describe "
|
72
|
+
describe ".save!" do
|
99
73
|
it 'throws an exception if save fails' do
|
100
|
-
unsaved_person.
|
74
|
+
unsaved_person.stub(:graph_uri).and_return(nil) # force a failure
|
101
75
|
lambda {unsaved_person.save!}.should raise_error(Tripod::Errors::Validations)
|
102
76
|
end
|
103
77
|
end
|
104
78
|
|
79
|
+
describe '.update_attribute' do
|
80
|
+
let (:person) { Person.new('http://newperson') }
|
81
|
+
before { person.stub(:save) }
|
82
|
+
|
83
|
+
it 'should write the attribute' do
|
84
|
+
person.update_attribute(:name, 'Bob')
|
85
|
+
person.name.should == 'Bob'
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should save the record' do
|
89
|
+
person.should_receive(:save)
|
90
|
+
person.update_attribute(:name, 'Bob')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '.update_attributes' do
|
95
|
+
let (:person) { Person.new('http://newperson') }
|
96
|
+
before { person.stub(:save) }
|
97
|
+
|
98
|
+
it 'should assign the attributes' do
|
99
|
+
person.update_attributes(:name => 'Bob')
|
100
|
+
person.name.should == 'Bob'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should save the record' do
|
104
|
+
person.should_receive(:save)
|
105
|
+
person.update_attributes(:name => 'Bob')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
105
109
|
describe "transactions" do
|
106
110
|
|
107
|
-
it "only
|
111
|
+
it "only saves on commit" do
|
108
112
|
|
109
113
|
transaction = Tripod::Persistence::Transaction.new
|
110
114
|
|
111
115
|
unsaved_person.save(transaction: transaction)
|
112
|
-
saved_person
|
116
|
+
saved_person.write_predicate('http://pred2', 'blah')
|
113
117
|
saved_person.save(transaction: transaction)
|
114
118
|
|
115
119
|
# nothing should have changed yet.
|
116
120
|
lambda {Person.find(unsaved_person.uri)}.should raise_error(Tripod::Errors::ResourceNotFound)
|
117
|
-
Person.find(saved_person.uri)
|
121
|
+
Person.find(saved_person.uri).read_predicate('http://pred2').first.to_s.should == RDF::URI.new('http://obj2').to_s
|
118
122
|
|
119
123
|
transaction.commit
|
120
124
|
|
121
125
|
# things should have changed now.
|
122
126
|
lambda {Person.find(unsaved_person.uri)}.should_not raise_error()
|
123
|
-
Person.find(saved_person.uri)
|
127
|
+
Person.find(saved_person.uri).read_predicate('http://pred2').first.should == 'blah'
|
124
128
|
|
125
129
|
end
|
126
130
|
|
127
131
|
it "silently ignore invalid saves" do
|
128
132
|
transaction = Tripod::Persistence::Transaction.new
|
129
133
|
|
130
|
-
unsaved_person.
|
134
|
+
unsaved_person.stub(:graph_uri).and_return(nil) # force a failure
|
131
135
|
unsaved_person.save(transaction: transaction).should be_false
|
132
136
|
|
133
|
-
saved_person
|
137
|
+
saved_person.write_predicate('http://pred2', 'blah')
|
134
138
|
saved_person.save(transaction: transaction).should be_true
|
135
139
|
|
136
140
|
transaction.commit
|
@@ -142,7 +146,7 @@ describe Tripod::Persistence do
|
|
142
146
|
lambda {Person.find(unsaved_person.uri)}.should raise_error(Tripod::Errors::ResourceNotFound)
|
143
147
|
|
144
148
|
# saved person SHOULD be updated
|
145
|
-
Person.find(saved_person.uri)
|
149
|
+
Person.find(saved_person.uri).read_predicate('http://pred2').first.should == 'blah'
|
146
150
|
end
|
147
151
|
|
148
152
|
it "can be aborted" do
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tripod::Predicates do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@uri = 'http://ric'
|
7
|
+
@graph = RDF::Graph.new('http://graph')
|
8
|
+
|
9
|
+
stmt = RDF::Statement.new
|
10
|
+
stmt.subject = RDF::URI.new(@uri)
|
11
|
+
stmt.predicate = RDF::URI.new('http://blog')
|
12
|
+
stmt.object = RDF::URI.new('http://blog1')
|
13
|
+
@graph << stmt
|
14
|
+
|
15
|
+
stmt2 = RDF::Statement.new
|
16
|
+
stmt2.subject = RDF::URI.new(@uri)
|
17
|
+
stmt2.predicate = RDF::URI.new('http://blog')
|
18
|
+
stmt2.object = RDF::URI.new('http://blog2')
|
19
|
+
@graph << stmt2
|
20
|
+
|
21
|
+
stmt3 = RDF::Statement.new
|
22
|
+
stmt3.subject = RDF::URI.new(@uri)
|
23
|
+
stmt3.predicate = RDF::URI.new('http://name')
|
24
|
+
stmt3.object = "ric"
|
25
|
+
@graph << stmt3
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:person) do
|
29
|
+
p = Person.new(@uri)
|
30
|
+
p.hydrate!(:graph => @graph)
|
31
|
+
p
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#read_predicate" do
|
35
|
+
it 'returns the values where the predicate matches' do
|
36
|
+
values = person.read_predicate('http://blog')
|
37
|
+
values.length.should == 2
|
38
|
+
values.first.should == RDF::URI('http://blog1')
|
39
|
+
values[1].should == RDF::URI('http://blog2')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#write_predicate' do
|
44
|
+
|
45
|
+
context 'single term passed' do
|
46
|
+
it 'replaces the values where the predicate matches' do
|
47
|
+
person.write_predicate('http://name', 'richard')
|
48
|
+
person.read_predicate('http://name').should == [RDF::Literal.new('richard')]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'multiple terms passed' do
|
53
|
+
it 'replaces the values where the predicate matches' do
|
54
|
+
person.write_predicate('http://name', ['richard', 'ric', 'ricardo'])
|
55
|
+
person.read_predicate('http://name').should == [RDF::Literal.new('richard'), RDF::Literal.new('ric'), RDF::Literal.new('ricardo')]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#remove_predicate' do
|
62
|
+
it 'remnoves the values where the predicate matches' do
|
63
|
+
person.remove_predicate('http://blog')
|
64
|
+
person.read_predicate('http://blog').should be_empty
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#append_to_predicate" do
|
69
|
+
it 'appends values to the existing values for the predicate' do
|
70
|
+
person.append_to_predicate('http://name', 'rico')
|
71
|
+
person.read_predicate('http://name').should == [RDF::Literal.new('ric'), RDF::Literal.new('rico')]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#predicates" do
|
76
|
+
it "returns a list of unique RDF::URIs for the predicates set on this resource" do
|
77
|
+
person.predicates.length.should == 2
|
78
|
+
person.predicates.should == [RDF::URI('http://blog'), RDF::URI('http://name')]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -4,51 +4,78 @@ describe Tripod::Repository do
|
|
4
4
|
|
5
5
|
describe "#hydrate" do
|
6
6
|
|
7
|
-
context 'no uri set' do
|
8
|
-
let(:person) do
|
9
|
-
Person.new
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'rasies a UriNotSet error' do
|
13
|
-
lambda { person.hydrate! }.should raise_error(Tripod::Errors::UriNotSet)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
7
|
context 'uri set' do
|
18
8
|
|
19
9
|
before do
|
20
10
|
@uri = 'http://foobar'
|
21
|
-
@
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
11
|
+
@uri2 = 'http://bazbar'
|
12
|
+
@graph_uri = 'http://graph'
|
13
|
+
|
14
|
+
p1 = Person.new(@uri, @graph_uri)
|
15
|
+
p1.write_predicate('http://pred', RDF::URI.new('http://obj'))
|
16
|
+
p1.write_predicate('http://pred2', RDF::URI.new('http://obj2'))
|
17
|
+
p1.write_predicate('http://pred3', 'literal')
|
18
|
+
p1.save!
|
28
19
|
end
|
29
20
|
|
30
21
|
let(:person) do
|
31
|
-
Person.new(@uri)
|
22
|
+
Person.new(@uri, @graph_uri)
|
32
23
|
end
|
33
24
|
|
34
25
|
context 'no graph passed' do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
26
|
+
|
27
|
+
context 'no predicate restrictions passed' do
|
28
|
+
|
29
|
+
it 'populates the repository with a graph of triples from the db' do
|
30
|
+
Tripod::SparqlClient::Query.should_receive(:describe).with("DESCRIBE <#{@uri}>").and_call_original
|
31
|
+
person.hydrate!
|
32
|
+
person.repository.should_not be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'single predicate restriction passed' do
|
38
|
+
it 'calls the right CONSTRUCT query' do
|
39
|
+
Tripod::SparqlClient::Query.should_receive(:construct).with("CONSTRUCT { <http://foobar> ?p ?o } WHERE { <http://foobar> ?p ?o . FILTER (?p = <http://pred>)}").and_call_original
|
40
|
+
person.hydrate!(:only => 'http://pred')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'only populates the right predicates' do
|
44
|
+
person.hydrate!(:only => 'http://pred')
|
45
|
+
person.predicates.length.should ==1
|
46
|
+
person.predicates.should == [RDF::URI('http://pred')]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'multiple predicate restrictions passed' do
|
51
|
+
it 'calls the right CONSTRUCT query' do
|
52
|
+
Tripod::SparqlClient::Query.should_receive(:construct).with("CONSTRUCT { <http://foobar> ?p ?o } WHERE { <http://foobar> ?p ?o . FILTER (?p = <http://pred> || ?p = <http://anotherpred>)}").and_call_original
|
53
|
+
person.hydrate!(:only => ['http://pred', 'http://anotherpred'])
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'only populates the right predicates' do
|
57
|
+
person.hydrate!(:only => ['http://pred2', 'http://pred'])
|
58
|
+
person.predicates.length.should == 2
|
59
|
+
person.predicates.should == [RDF::URI('http://pred'), RDF::URI('http://pred2')]
|
60
|
+
end
|
39
61
|
end
|
40
62
|
end
|
41
63
|
|
42
64
|
context 'graph passed' do
|
43
65
|
it 'populates the repository with the graph of triples passed in, ingoring triples not about this resource' do
|
66
|
+
@graph = RDF::Graph.new
|
67
|
+
|
68
|
+
person.repository.statements.each do |s|
|
69
|
+
@graph << s
|
70
|
+
end
|
44
71
|
|
45
72
|
@graph << RDF::Statement.new( 'http://anotherresource', 'http://pred', 'http://obj')
|
46
|
-
@graph.statements.count.should ==2
|
73
|
+
@graph.statements.count.should ==2 # there'll already be a statement about type in the person.
|
47
74
|
|
48
|
-
person.hydrate!(@graph)
|
75
|
+
person.hydrate!(:graph => @graph)
|
49
76
|
person.repository.should_not be_empty
|
50
|
-
person.repository.statements.count.should == 1 # not the extra
|
51
|
-
person.repository.statements.first.should == @
|
77
|
+
person.repository.statements.count.should == 1 # not the extra ones
|
78
|
+
person.repository.statements.first.should == @graph.statements.first
|
52
79
|
end
|
53
80
|
end
|
54
81
|
|