tripod 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -34,7 +34,9 @@ module Tripod::Fields
34
34
 
35
35
 
36
36
  def new_value_for_field(value, field)
37
- if field.datatype
37
+ if field.is_uri?
38
+ RDF::URI.new(value.to_s)
39
+ elsif field.datatype
38
40
  RDF::Literal.new(value, :datatype => field.datatype)
39
41
  else
40
42
  value
@@ -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
@@ -28,13 +28,19 @@ module Tripod::Repository
28
28
 
29
29
  if graph
30
30
  graph.each_statement do |statement|
31
- # only use statements about this resource for hydrating
32
- if statement.subject.to_s == @uri.to_s
33
- @repository << statement
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
- triples = Tripod::SparqlClient::Query.query("DESCRIBE <#{uri}>", "application/n-triples")
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
@@ -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([format, headers, sparql].join(" "))
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()
@@ -1,3 +1,3 @@
1
1
  module Tripod
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -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]
@@ -8,7 +8,6 @@ describe Tripod::Fields do
8
8
  b = Person.new('http://example.com/id/barry')
9
9
  b.name = 'Barry'
10
10
  b
11
- b
12
11
  end
13
12
 
14
13
  it "creates a getter for the field, which accesses data for the predicate, returning a single String" do
@@ -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
- it 'should use that graph to call new' do
52
- ric # trigger the lazy load
53
- Person.should_receive(:new).with(ric.uri, 'http://example.com/graphx').and_call_original
54
- Person.find(ric.uri, "http://example.com/graphx")
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
- context 'no graph passed' do
25
+ let(:graphless_resource) do
26
+ Resource.new(@uri)
27
+ end
26
28
 
27
- context 'no predicate restrictions passed' do
29
+ context 'no graph passed' do
28
30
 
29
- it 'populates the repository with a graph of triples from the db' do
30
- Tripod::SparqlClient::Query.should_receive(:query).with("DESCRIBE <#{@uri}>", "application/n-triples").and_call_original
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, ingoring triples not about this resource' do
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 == 1 # not the extra ones
52
- person.repository.statements.first.should == @graph.statements.first
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.0
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-13 00:00:00.000000000 Z
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: &70364886263520 !ruby/object:Gem::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: *70364886263520
26
+ version_requirements: *70208187066620
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
- requirement: &70364886262400 !ruby/object:Gem::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: *70364886262400
37
+ version_requirements: *70208187061260
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: equivalent-xml
40
- requirement: &70364886261680 !ruby/object:Gem::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: *70364886261680
48
+ version_requirements: *70208187091120
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rdf
51
- requirement: &70364886260440 !ruby/object:Gem::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: *70364886260440
59
+ version_requirements: *70208187100360
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rdf-rdfxml
62
- requirement: &70364886259940 !ruby/object:Gem::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: *70364886259940
70
+ version_requirements: *70208187094320
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: rdf-n3
73
- requirement: &70364886258140 !ruby/object:Gem::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: *70364886258140
81
+ version_requirements: *70208186978440
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: rdf-json
84
- requirement: &70364886255600 !ruby/object:Gem::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: *70364886255600
92
+ version_requirements: *70208186977380
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: json-ld
95
- requirement: &70364886254440 !ruby/object:Gem::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: *70364886254440
103
+ version_requirements: *70208186975660
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: guid
106
- requirement: &70364886240960 !ruby/object:Gem::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: *70364886240960
114
+ version_requirements: *70208186974980
115
115
  - !ruby/object:Gem::Dependency
116
116
  name: dalli
117
- requirement: &70364886240040 !ruby/object:Gem::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: *70364886240040
125
+ version_requirements: *70208186973620
126
126
  description: RDF ruby ORM
127
127
  email:
128
128
  - ric@swirrl.com