tripod 0.4.0 → 0.4.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/lib/tripod/errors/resource_not_found.rb +12 -0
- data/lib/tripod/fields/standard.rb +3 -2
- data/lib/tripod/fields.rb +3 -1
- data/lib/tripod/finders.rb +2 -2
- data/lib/tripod/repository.rb +20 -5
- data/lib/tripod/sparql_client.rb +5 -1
- data/lib/tripod/version.rb +1 -1
- data/spec/app/models/person.rb +1 -1
- data/spec/tripod/attributes_spec.rb +16 -3
- data/spec/tripod/fields_spec.rb +0 -1
- data/spec/tripod/finders_spec.rb +27 -6
- data/spec/tripod/repository_spec.rb +23 -8
- metadata +22 -22
@@ -3,6 +3,18 @@ module Tripod::Errors
|
|
3
3
|
|
4
4
|
# not found error.
|
5
5
|
class ResourceNotFound < StandardError
|
6
|
+
|
7
|
+
attr_accessor :uri
|
8
|
+
|
9
|
+
def initialize(uri=nil)
|
10
|
+
@uri = uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
msg = "Resource Not Found"
|
15
|
+
msg += ": #{@uri.to_s}" if @uri
|
16
|
+
msg
|
17
|
+
end
|
6
18
|
end
|
7
19
|
|
8
20
|
end
|
@@ -4,7 +4,8 @@ module Tripod::Fields
|
|
4
4
|
class Standard
|
5
5
|
|
6
6
|
# Set readers for the instance variables.
|
7
|
-
attr_accessor :name, :predicate, :options, :datatype, :multivalued
|
7
|
+
attr_accessor :name, :predicate, :options, :datatype, :is_uri, :multivalued
|
8
|
+
alias_method :is_uri?, :is_uri
|
8
9
|
|
9
10
|
# Create the new field with a name and optional additional options.
|
10
11
|
#
|
@@ -22,8 +23,8 @@ module Tripod::Fields
|
|
22
23
|
@options = options
|
23
24
|
@predicate = RDF::URI.new(predicate.to_s)
|
24
25
|
@datatype = RDF::URI.new(options[:datatype].to_s) if options[:datatype]
|
26
|
+
@is_uri = !!options[:is_uri]
|
25
27
|
@multivalued = options[:multivalued] || false
|
26
28
|
end
|
27
|
-
|
28
29
|
end
|
29
30
|
end
|
data/lib/tripod/fields.rb
CHANGED
data/lib/tripod/finders.rb
CHANGED
@@ -30,7 +30,7 @@ module Tripod::Finders
|
|
30
30
|
if result.length > 0
|
31
31
|
graph_uri = result[0]["g"]["value"]
|
32
32
|
else
|
33
|
-
raise Tripod::Errors::ResourceNotFound.new
|
33
|
+
raise Tripod::Errors::ResourceNotFound.new(uri)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -42,7 +42,7 @@ module Tripod::Finders
|
|
42
42
|
|
43
43
|
# check that there are triples for the resource (catches case when someone has deleted data
|
44
44
|
# between our original check for the graph and hydrating the object.
|
45
|
-
raise Tripod::Errors::ResourceNotFound.new if resource.repository.empty?
|
45
|
+
raise Tripod::Errors::ResourceNotFound.new(uri) if resource.repository.empty?
|
46
46
|
|
47
47
|
# return the instantiated, hydrated resource
|
48
48
|
resource
|
data/lib/tripod/repository.rb
CHANGED
@@ -28,13 +28,19 @@ module Tripod::Repository
|
|
28
28
|
|
29
29
|
if graph
|
30
30
|
graph.each_statement do |statement|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
end
|
31
|
+
# Note that we use all statements, even those not about this resource, in case we're being
|
32
|
+
# passed eager-loaded ones.
|
33
|
+
@repository << statement
|
35
34
|
end
|
36
35
|
else
|
37
|
-
|
36
|
+
|
37
|
+
graph_selector = self.graph_uri.present? ? "<#{graph_uri.to_s}>" : "?g"
|
38
|
+
|
39
|
+
triples = Tripod::SparqlClient::Query.query(
|
40
|
+
"CONSTRUCT {<#{uri}> ?p ?o} WHERE { GRAPH #{graph_selector} { <#{uri}> ?p ?o } }",
|
41
|
+
"application/n-triples"
|
42
|
+
)
|
43
|
+
|
38
44
|
@repository = RDF::Repository.new
|
39
45
|
RDF::Reader.for(:ntriples).new(triples) do |reader|
|
40
46
|
reader.each_statement do |statement|
|
@@ -45,6 +51,15 @@ module Tripod::Repository
|
|
45
51
|
|
46
52
|
end
|
47
53
|
|
54
|
+
# returns a graph of all triples in the repository
|
55
|
+
def repository_as_graph
|
56
|
+
g = RDF::Graph.new
|
57
|
+
@repository.each_statement do |s|
|
58
|
+
g << s
|
59
|
+
end
|
60
|
+
g
|
61
|
+
end
|
62
|
+
|
48
63
|
# returns a graph of triples from the underlying repository where this resource's uri is the subject.
|
49
64
|
def get_triples_for_this_resource
|
50
65
|
triples_graph = RDF::Graph.new
|
data/lib/tripod/sparql_client.rb
CHANGED
@@ -17,6 +17,10 @@ module Tripod::SparqlClient
|
|
17
17
|
def self.query(sparql, accept_header, extra_params={})
|
18
18
|
|
19
19
|
begin
|
20
|
+
if defined?(Rails)
|
21
|
+
Rails.logger.debug "TRIPOD: About to run query:"
|
22
|
+
Rails.logger.debug sparql
|
23
|
+
end
|
20
24
|
params = {:query => sparql}.merge(extra_params)
|
21
25
|
hdrs = {:accept => accept_header, :params => params}
|
22
26
|
|
@@ -33,7 +37,7 @@ module Tripod::SparqlClient
|
|
33
37
|
if Tripod.cache_store # if a cache store is configured
|
34
38
|
# SHA-2 the key to keep the it within the small limit for many cache stores (e.g. Memcached is 250bytes)
|
35
39
|
# Note: SHA2's are pretty certain to be unique http://en.wikipedia.org/wiki/SHA-2.
|
36
|
-
key = 'SPARQL-QUERY-' + Digest::SHA2.hexdigest([
|
40
|
+
key = 'SPARQL-QUERY-' + Digest::SHA2.hexdigest([extra_params, accept_header, sparql].join(" "))
|
37
41
|
Tripod.cache_store.fetch(key, &make_the_call)
|
38
42
|
else
|
39
43
|
make_the_call.call()
|
data/lib/tripod/version.rb
CHANGED
data/spec/app/models/person.rb
CHANGED
@@ -6,7 +6,7 @@ class Person
|
|
6
6
|
graph_uri 'http://example.com/graph'
|
7
7
|
|
8
8
|
field :name, 'http://example.com/name'
|
9
|
-
field :father, 'http://example.com/father'
|
9
|
+
field :father, 'http://example.com/father', :is_uri => true
|
10
10
|
field :knows, 'http://example.com/knows', :multivalued => true
|
11
11
|
field :aliases, 'http://exmample.com/alias', :multivalued => true
|
12
12
|
field :age, 'http://example.com/age', :datatype => RDF::XSD.integer
|
@@ -26,10 +26,7 @@ describe Tripod::Attributes do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
context "for a uri" do
|
29
|
-
|
30
29
|
it "should return an RDF::URI" do
|
31
|
-
puts person[:father]
|
32
|
-
|
33
30
|
person[:father].class.should == RDF::URI
|
34
31
|
end
|
35
32
|
|
@@ -62,6 +59,15 @@ describe Tripod::Attributes do
|
|
62
59
|
it "should return a single value" do
|
63
60
|
person.read_attribute(:hat_type, field).should == 'fez'
|
64
61
|
end
|
62
|
+
|
63
|
+
context "and the value is a URI" do
|
64
|
+
let(:field) { Person.send(:field_for, :hat_type, 'http://example.com/hat', {is_uri: true}) }
|
65
|
+
before do
|
66
|
+
person.stub(:read_predicate).with('http://example.com/hat').and_return(['fez'])
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
65
71
|
end
|
66
72
|
|
67
73
|
context "where field is given and is multi-valued" do
|
@@ -95,6 +101,13 @@ describe Tripod::Attributes do
|
|
95
101
|
person.read_predicate('http://example.com/age').first.datatype.should == RDF::XSD.integer
|
96
102
|
end
|
97
103
|
|
104
|
+
context "where the attribute is a uri" do
|
105
|
+
it "should convert a string to an RDF::URI" do
|
106
|
+
person[:father] = 'http://example.com/darth'
|
107
|
+
person.read_predicate('http://example.com/father').first.should be_a(RDF::URI)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
98
111
|
context "where the attribute is multi-valued" do
|
99
112
|
it "should co-erce all the values to the correct datatype" do
|
100
113
|
person[:important_dates] = [Date.today]
|
data/spec/tripod/fields_spec.rb
CHANGED
data/spec/tripod/finders_spec.rb
CHANGED
@@ -2,14 +2,14 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Tripod::Finders do
|
4
4
|
|
5
|
-
let(:ric) do
|
5
|
+
let!(:ric) do
|
6
6
|
r = Person.new('http://example.com/id/ric')
|
7
7
|
r.name = "ric"
|
8
8
|
r.knows = RDF::URI.new("http://example.com/id/bill")
|
9
9
|
r
|
10
10
|
end
|
11
11
|
|
12
|
-
let(:bill) do
|
12
|
+
let!(:bill) do
|
13
13
|
b = Person.new('http://example.com/id/bill')
|
14
14
|
b.name = "bill"
|
15
15
|
b
|
@@ -48,10 +48,31 @@ describe Tripod::Finders do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
context 'with graph_uri supplied' do
|
51
|
-
|
52
|
-
|
53
|
-
Person.
|
54
|
-
|
51
|
+
|
52
|
+
let!(:another_person) do
|
53
|
+
p = Person.new('http://example.com/anotherperson', 'http://example.com/graphx')
|
54
|
+
p.name = 'a.n.other'
|
55
|
+
p.save!
|
56
|
+
p
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when there are triples about the resource in that graph' do
|
60
|
+
|
61
|
+
it 'should use that graph to call new' do
|
62
|
+
Person.should_receive(:new).with(another_person.uri, 'http://example.com/graphx').and_call_original
|
63
|
+
Person.find(another_person.uri, "http://example.com/graphx")
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when there are no triples about the resource in that graph' do
|
69
|
+
it 'should raise nto found' do
|
70
|
+
|
71
|
+
lambda {
|
72
|
+
Person.find(another_person.uri, "http://example.com/graphy")
|
73
|
+
}.should raise_error(Tripod::Errors::ResourceNotFound)
|
74
|
+
|
75
|
+
end
|
55
76
|
end
|
56
77
|
end
|
57
78
|
|
@@ -22,21 +22,36 @@ describe Tripod::Repository do
|
|
22
22
|
Person.new(@uri, @graph_uri)
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
let(:graphless_resource) do
|
26
|
+
Resource.new(@uri)
|
27
|
+
end
|
26
28
|
|
27
|
-
|
29
|
+
context 'no graph passed' do
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
+
context 'graph_uri set on object' do
|
32
|
+
it 'populates the object with triples, restricted to the graph_uri' do
|
33
|
+
Tripod::SparqlClient::Query.should_receive(:query).with(
|
34
|
+
"CONSTRUCT {<#{person.uri}> ?p ?o} WHERE { GRAPH <#{person.graph_uri}> { <#{person.uri}> ?p ?o } }",
|
35
|
+
"application/n-triples").and_call_original
|
31
36
|
person.hydrate!
|
32
37
|
person.repository.should_not be_empty
|
33
38
|
end
|
39
|
+
end
|
34
40
|
|
41
|
+
context 'graph_uri not set on object' do
|
42
|
+
it 'populates the object with triples, not to a graph' do
|
43
|
+
Tripod::SparqlClient::Query.should_receive(:query).with(
|
44
|
+
"CONSTRUCT {<#{graphless_resource.uri}> ?p ?o} WHERE { GRAPH ?g { <#{graphless_resource.uri}> ?p ?o } }",
|
45
|
+
"application/n-triples").and_call_original
|
46
|
+
graphless_resource.hydrate!
|
47
|
+
graphless_resource.repository.should_not be_empty
|
48
|
+
end
|
35
49
|
end
|
50
|
+
|
36
51
|
end
|
37
52
|
|
38
53
|
context 'graph passed' do
|
39
|
-
it 'populates the repository with the graph of triples passed in
|
54
|
+
it 'populates the repository with the graph of triples passed in' do
|
40
55
|
@graph = RDF::Graph.new
|
41
56
|
|
42
57
|
person.repository.statements.each do |s|
|
@@ -44,12 +59,12 @@ describe Tripod::Repository do
|
|
44
59
|
end
|
45
60
|
|
46
61
|
@graph << RDF::Statement.new( 'http://example.com/anotherresource', 'http://example.com/pred', 'http://example.com/obj')
|
47
|
-
@graph.statements.count.should ==2 # there'll already be a statement about type in the person.
|
62
|
+
@graph.statements.count.should == 2 # there'll already be a statement about type in the person.
|
48
63
|
|
49
64
|
person.hydrate!(:graph => @graph)
|
50
65
|
person.repository.should_not be_empty
|
51
|
-
person.repository.statements.count.should ==
|
52
|
-
person.repository.statements.
|
66
|
+
person.repository.statements.count.should == 2 # not the extra ones
|
67
|
+
person.repository.statements.to_a.should == @graph.statements.to_a
|
53
68
|
end
|
54
69
|
end
|
55
70
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tripod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-03-
|
14
|
+
date: 2013-03-21 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rest-client
|
18
|
-
requirement: &
|
18
|
+
requirement: &70208187066620 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,10 +23,10 @@ dependencies:
|
|
23
23
|
version: '0'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70208187066620
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
|
-
requirement: &
|
29
|
+
requirement: &70208187061260 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ~>
|
@@ -34,10 +34,10 @@ dependencies:
|
|
34
34
|
version: '3.1'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70208187061260
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: equivalent-xml
|
40
|
-
requirement: &
|
40
|
+
requirement: &70208187091120 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
@@ -45,10 +45,10 @@ dependencies:
|
|
45
45
|
version: '0'
|
46
46
|
type: :runtime
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70208187091120
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: rdf
|
51
|
-
requirement: &
|
51
|
+
requirement: &70208187100360 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ~>
|
@@ -56,10 +56,10 @@ dependencies:
|
|
56
56
|
version: '1.0'
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70208187100360
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: rdf-rdfxml
|
62
|
-
requirement: &
|
62
|
+
requirement: &70208187094320 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ! '>='
|
@@ -67,10 +67,10 @@ dependencies:
|
|
67
67
|
version: '0'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70208187094320
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: rdf-n3
|
73
|
-
requirement: &
|
73
|
+
requirement: &70208186978440 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - ! '>='
|
@@ -78,10 +78,10 @@ dependencies:
|
|
78
78
|
version: '0'
|
79
79
|
type: :runtime
|
80
80
|
prerelease: false
|
81
|
-
version_requirements: *
|
81
|
+
version_requirements: *70208186978440
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
name: rdf-json
|
84
|
-
requirement: &
|
84
|
+
requirement: &70208186977380 !ruby/object:Gem::Requirement
|
85
85
|
none: false
|
86
86
|
requirements:
|
87
87
|
- - ! '>='
|
@@ -89,10 +89,10 @@ dependencies:
|
|
89
89
|
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
|
-
version_requirements: *
|
92
|
+
version_requirements: *70208186977380
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: json-ld
|
95
|
-
requirement: &
|
95
|
+
requirement: &70208186975660 !ruby/object:Gem::Requirement
|
96
96
|
none: false
|
97
97
|
requirements:
|
98
98
|
- - ! '>='
|
@@ -100,10 +100,10 @@ dependencies:
|
|
100
100
|
version: '0'
|
101
101
|
type: :runtime
|
102
102
|
prerelease: false
|
103
|
-
version_requirements: *
|
103
|
+
version_requirements: *70208186975660
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
105
|
name: guid
|
106
|
-
requirement: &
|
106
|
+
requirement: &70208186974980 !ruby/object:Gem::Requirement
|
107
107
|
none: false
|
108
108
|
requirements:
|
109
109
|
- - ! '>='
|
@@ -111,10 +111,10 @@ dependencies:
|
|
111
111
|
version: '0'
|
112
112
|
type: :runtime
|
113
113
|
prerelease: false
|
114
|
-
version_requirements: *
|
114
|
+
version_requirements: *70208186974980
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
116
|
name: dalli
|
117
|
-
requirement: &
|
117
|
+
requirement: &70208186973620 !ruby/object:Gem::Requirement
|
118
118
|
none: false
|
119
119
|
requirements:
|
120
120
|
- - ~>
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
version: '2.6'
|
123
123
|
type: :runtime
|
124
124
|
prerelease: false
|
125
|
-
version_requirements: *
|
125
|
+
version_requirements: *70208186973620
|
126
126
|
description: RDF ruby ORM
|
127
127
|
email:
|
128
128
|
- ric@swirrl.com
|