tripod 0.3.1 → 0.3.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 CHANGED
@@ -103,9 +103,9 @@ Note: Tripod doesn't supply a database. You need to install one. I recommend [Fu
103
103
  # It doesn't actually do anything against the DB until you run resources, first, or count on it.
104
104
  # (from Tripod::CriteriaExecution)
105
105
 
106
- Person.all #=> returns a Tripod::Criteria object which selects all resources of rdf_type http://person
106
+ Person.all #=> returns a Tripod::Criteria object which selects all resources of rdf_type http://person, in the http://people graph
107
107
 
108
- Resource.all #=> returns a criteria object to return resources in the database (as no rdf_type specified at class level)
108
+ Resource.all #=> returns a criteria object to return resources in the database (as no rdf_type or graph_uri specified at class level)
109
109
 
110
110
  Person.all.resources #=> returns all the actual resources for the criteria object, as an array
111
111
 
@@ -116,6 +116,8 @@ Note: Tripod doesn't supply a database. You need to install one. I recommend [Fu
116
116
  # note that you need to use ?uri as the variable for the subject.
117
117
  Person.where("?uri <http://name> 'Joe'") #=> returns a Tripod::Criteria object
118
118
 
119
+ Resource.graph("http://mygraph") #=> Retruns a criteria object with a graph restriction (note: if graph_uri set on the class, it will default to using this)
120
+
119
121
  ## Chainable criteria
120
122
 
121
123
  Person.all.where("?uri <http://name> 'Ric'").where("?uri <http://knows> <http://asa>).first
@@ -17,6 +17,7 @@ module Tripod
17
17
  attr_accessor :limit_clause
18
18
  attr_accessor :order_clause
19
19
  attr_accessor :offset_clause
20
+ attr_accessor :graph_uri
20
21
 
21
22
  def initialize(resource_class)
22
23
  self.resource_class = resource_class
@@ -28,6 +29,8 @@ module Tripod
28
29
  else
29
30
  self.where("?uri ?p ?o")
30
31
  end
32
+
33
+ self.graph_uri = resource_class._GRAPH_URI.to_s if resource_class._GRAPH_URI
31
34
  end
32
35
 
33
36
  # they're equal if they return the same query
@@ -73,5 +76,16 @@ module Tripod
73
76
  self
74
77
  end
75
78
 
79
+ # Restrict htis query to the graph uri passed in
80
+ #
81
+ # @example .graph(RDF::URI.new('http://graphoid')
82
+ # @example .graph('http://graphoid')
83
+ #
84
+ # @param [ Stirng, RDF::URI ] The graph uri
85
+ #
86
+ # @return [ Tripod::Criteria ] A criteria object
87
+ def graph(graph_uri)
88
+ self.graph_uri = graph_uri.to_s
89
+ end
76
90
  end
77
91
  end
@@ -33,8 +33,8 @@ module Tripod
33
33
  private
34
34
 
35
35
  def resources_from_sparql(sparql)
36
- uris_and_graphs = select_uris_and_graphs(sparql)
37
- create_and_hydrate_resources(uris_and_graphs)
36
+ uris_and_graphs = self.resource_class._select_uris_and_graphs(sparql)
37
+ self.resource_class._create_and_hydrate_resources(uris_and_graphs)
38
38
  end
39
39
 
40
40
  def build_select_query
@@ -44,64 +44,19 @@ module Tripod
44
44
  extras(limit_clause)
45
45
  extras(offset_clause)
46
46
 
47
- # build the query.
48
- select_query = "SELECT ?uri ?graph WHERE { GRAPH ?graph { "
47
+ if graph_uri
48
+ select_query = "SELECT ?uri (<#{graph_uri}> as ?graph) WHERE { GRAPH <#{graph_uri}> "
49
+ else
50
+ select_query = "SELECT ?uri ?graph WHERE { GRAPH ?graph "
51
+ end
52
+
53
+ select_query += "{ "
49
54
  select_query += self.where_clauses.join(" . ")
50
55
  select_query += " } } "
51
56
  select_query += self.extra_clauses.join(" ")
52
57
  select_query.strip
53
58
  end
54
59
 
55
- # create and hydrate the resources identified in uris_and_graphs.
56
- # Note: if any of the graphs are not set, those resources can still be constructed, but not persisted back to DB.
57
- def create_and_hydrate_resources(uris_and_graphs)
58
-
59
- graph = self.resource_class.describe_uris(uris_and_graphs.keys) #uses the resource_class on the criteria object
60
- repo = self.resource_class.add_data_to_repository(graph)
61
-
62
- resources = []
63
-
64
- uris_and_graphs.each_pair do |u,g|
65
-
66
- # instantiate a new resource
67
- r = self.resource_class.new(u,g)
68
-
69
- # make a graph of data for this resource's uri
70
- data_graph = RDF::Graph.new
71
- repo.query( [RDF::URI.new(u), :predicate, :object] ) do |statement|
72
- data_graph << statement
73
- end
74
-
75
- # use it to hydrate this resource
76
- r.hydrate!(:graph => data_graph)
77
- r.new_record = false
78
- resources << r
79
- end
80
-
81
- resources
82
- end
83
-
84
-
85
- # based on the query passed in, build a hash of uris->graphs
86
- # @param [ String] sparql. The sparql query
87
- # @param [ Hash ] opts. A hash of options.
88
- #
89
- # @option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri'
90
- # @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
91
- def select_uris_and_graphs(sparql, opts={})
92
- select_results = Tripod::SparqlClient::Query.select(sparql)
93
-
94
- uris_and_graphs = {}
95
-
96
- select_results.each do |r|
97
- uri_variable = opts[:uri_variable] || 'uri'
98
- graph_variable = opts[:graph_variable] || 'graph'
99
- uris_and_graphs[ r[uri_variable]["value"] ] = r[graph_variable]["value"]
100
- end
101
-
102
- uris_and_graphs
103
- end
104
-
105
60
  end
106
61
 
107
62
  end
@@ -48,6 +48,24 @@ module Tripod::Finders
48
48
  resource
49
49
  end
50
50
 
51
+ # Find a collection of +Resource+s by a SPARQL select statement which returns their uris.
52
+ # Under the hood, this only executes two queries: a select, then a describe.
53
+ #
54
+ # @example
55
+ # Person.find_by_sparql('SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } } LIMIT 3')
56
+ #
57
+ # @param [ String ] sparql_query. A sparql query which returns a list of uris of the objects.
58
+ # @param [ Hash ] opts. A hash of options.
59
+ #
60
+ # @option options [ String ] uri_variable The name of the uri variable in thh query, if not 'uri'
61
+ # @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
62
+ #
63
+ # @return [ Array ] An array of hydrated resources of this class's type.
64
+ def find_by_sparql(sparql_query, opts={})
65
+ uris_and_graphs = _select_uris_and_graphs(criteria, opts)
66
+ _create_and_hydrate_resources(uris_and_graphs)
67
+ end
68
+
51
69
  # execute a where clause on this resource.
52
70
  # returns a criteria object
53
71
  def where(sparql_snippet)
@@ -91,5 +109,57 @@ module Tripod::Finders
91
109
  graph
92
110
  end
93
111
 
112
+ # THESE AREN'T INTENDED TO BE PART OF THE PUBLIC API:
113
+
114
+ # create and hydrate the resources identified in uris_and_graphs.
115
+ # Note: if any of the graphs are not set, those resources can still be constructed, but not persisted back to DB.
116
+ def _create_and_hydrate_resources(uris_and_graphs)
117
+
118
+ graph = describe_uris(uris_and_graphs.keys) #uses the resource_class on the criteria object
119
+ repo = add_data_to_repository(graph)
120
+
121
+ resources = []
122
+
123
+ uris_and_graphs.each_pair do |u,g|
124
+
125
+ # instantiate a new resource
126
+ r = self.new(u,g)
127
+
128
+ # make a graph of data for this resource's uri
129
+ data_graph = RDF::Graph.new
130
+ repo.query( [RDF::URI.new(u), :predicate, :object] ) do |statement|
131
+ data_graph << statement
132
+ end
133
+
134
+ # use it to hydrate this resource
135
+ r.hydrate!(:graph => data_graph)
136
+ r.new_record = false
137
+ resources << r
138
+ end
139
+
140
+ resources
141
+ end
142
+
143
+
144
+ # based on the query passed in, build a hash of uris->graphs
145
+ # @param [ String] sparql. The sparql query
146
+ # @param [ Hash ] opts. A hash of options.
147
+ #
148
+ # @option options [ String ] uri_variable The name of the uri variable in the query, if not 'uri'
149
+ # @option options [ String ] graph_variable The name of the uri variable in thh query, if not 'graph'
150
+ def _select_uris_and_graphs(sparql, opts={})
151
+ select_results = Tripod::SparqlClient::Query.select(sparql)
152
+
153
+ uris_and_graphs = {}
154
+
155
+ select_results.each do |r|
156
+ uri_variable = opts[:uri_variable] || 'uri'
157
+ graph_variable = opts[:graph_variable] || 'graph'
158
+ uris_and_graphs[ r[uri_variable]["value"] ] = r[graph_variable]["value"]
159
+ end
160
+
161
+ uris_and_graphs
162
+ end
163
+
94
164
  end
95
165
  end
@@ -15,9 +15,8 @@ module Tripod
15
15
  cattr_accessor :KEYWORDS
16
16
  @@KEYWORDS = %w(CONSTRUCT ASK DESCRIBE SELECT)
17
17
 
18
- def initialize(query_string, parent_query=nil)
18
+ def initialize(query_string)
19
19
  @query = query_string
20
- @parent_query = parent_query
21
20
 
22
21
  if self.has_prefixes?
23
22
  @prefixes, @body = self.extract_prefixes
@@ -42,9 +41,14 @@ module Tripod
42
41
  return p.strip, b.strip
43
42
  end
44
43
 
45
- def as_count_query_str
44
+ def check_subqueryable!
46
45
  # only allow for selects
47
46
  raise SparqlQueryError.new("Can't turn this into a subquery") unless self.query_type == :select
47
+ end
48
+
49
+ def as_count_query_str
50
+
51
+ check_subqueryable!
48
52
 
49
53
  count_query = "SELECT COUNT(*) { #{self.body} }"
50
54
  count_query = "#{self.prefixes} #{count_query}" if self.prefixes
@@ -1,3 +1,3 @@
1
1
  module Tripod
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -11,34 +11,42 @@ describe Tripod::Criteria do
11
11
  end
12
12
 
13
13
  let(:john) do
14
- p = Person.new('http://john', 'http://people')
14
+ p = Person.new('http://john')
15
15
  p.name = "John"
16
16
  p
17
17
  end
18
18
 
19
19
  let(:barry) do
20
- p = Person.new('http://barry', 'http://people')
20
+ p = Person.new('http://barry')
21
21
  p.name = "Barry"
22
22
  p
23
23
  end
24
24
 
25
25
  describe "#build_select_query" do
26
26
 
27
- context "for a class with an rdf_type" do
27
+ context "for a class with an rdf_type and graph" do
28
28
  it "should return a SELECT query based with an rdf type restriction" do
29
- person_criteria.send(:build_select_query).should == "SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri a <http://person> } }"
29
+ person_criteria.send(:build_select_query).should == "SELECT ?uri (<http://graph> as ?graph) WHERE { GRAPH <http://graph> { ?uri a <http://person> } }"
30
30
  end
31
31
 
32
32
  context "and extra restrictions" do
33
33
  before { person_criteria.where("[pattern]") }
34
34
 
35
- it "should return a SELECT query with the extra restriction and rdf type restriction" do
36
- person_criteria.send(:build_select_query).should == "SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri a <http://person> . [pattern] } }"
35
+ it "should return a SELECT query with the extra restriction" do
36
+ person_criteria.send(:build_select_query).should == "SELECT ?uri (<http://graph> as ?graph) WHERE { GRAPH <http://graph> { ?uri a <http://person> . [pattern] } }"
37
+ end
38
+ end
39
+
40
+ context "with an overriden graph" do
41
+ before { person_criteria.graph("http://anothergraph") }
42
+
43
+ it "should override the graph in the query" do
44
+ person_criteria.send(:build_select_query).should == "SELECT ?uri (<http://anothergraph> as ?graph) WHERE { GRAPH <http://anothergraph> { ?uri a <http://person> } }"
37
45
  end
38
46
  end
39
47
  end
40
48
 
41
- context "for a class without an rdf_type" do
49
+ context "for a class without an rdf_type and graph" do
42
50
  it "should return a SELECT query without an rdf_type restriction" do
43
51
  resource_criteria.send(:build_select_query).should == "SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } }"
44
52
  end
@@ -50,6 +58,14 @@ describe Tripod::Criteria do
50
58
  resource_criteria.send(:build_select_query).should == "SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o . [pattern] } }"
51
59
  end
52
60
  end
61
+
62
+ context "with a graph set" do
63
+ before { resource_criteria.graph("http://graphy") }
64
+
65
+ it "should override the graph in the query" do
66
+ resource_criteria.send(:build_select_query).should == "SELECT ?uri (<http://graphy> as ?graph) WHERE { GRAPH <http://graphy> { ?uri ?p ?o } }"
67
+ end
68
+ end
53
69
  end
54
70
 
55
71
  context "with extras" do
@@ -134,7 +150,7 @@ describe Tripod::Criteria do
134
150
  let(:chained_criteria) { Person.where("?uri <http://name> ?name").limit(1).offset(0).order("DESC(?name)") }
135
151
 
136
152
  it "should run the right Sparql" do
137
- sparql = "SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri a <http://person> . ?uri <http://name> ?name } } ORDER BY DESC(?name) LIMIT 1 OFFSET 0"
153
+ sparql = "SELECT ?uri (<http://graph> as ?graph) WHERE { GRAPH <http://graph> { ?uri a <http://person> . ?uri <http://name> ?name } } ORDER BY DESC(?name) LIMIT 1 OFFSET 0"
138
154
  Tripod::SparqlClient::Query.should_receive(:select).with(sparql).and_call_original
139
155
  chained_criteria.resources
140
156
  end
@@ -107,4 +107,11 @@ describe Tripod::Criteria do
107
107
  end
108
108
  end
109
109
 
110
+ describe "#graph" do
111
+ it "sets the graph_uri for this criteria, as a string" do
112
+ resource_criteria.graph(RDF::URI("http://foobar"))
113
+ resource_criteria.graph_uri.should == "http://foobar"
114
+ end
115
+ end
116
+
110
117
  end
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.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -15,7 +15,7 @@ date: 2013-02-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rest-client
18
- requirement: &70281327925380 !ruby/object:Gem::Requirement
18
+ requirement: &70205083592080 !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: *70281327925380
26
+ version_requirements: *70205083592080
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
- requirement: &70281327924780 !ruby/object:Gem::Requirement
29
+ requirement: &70205083591380 !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: *70281327924780
37
+ version_requirements: *70205083591380
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: equivalent-xml
40
- requirement: &70281327924320 !ruby/object:Gem::Requirement
40
+ requirement: &70205083590920 !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: *70281327924320
48
+ version_requirements: *70205083590920
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rdf
51
- requirement: &70281327923680 !ruby/object:Gem::Requirement
51
+ requirement: &70205083589940 !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: *70281327923680
59
+ version_requirements: *70205083589940
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rdf-rdfxml
62
- requirement: &70281327923100 !ruby/object:Gem::Requirement
62
+ requirement: &70205083589120 !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: *70281327923100
70
+ version_requirements: *70205083589120
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: rdf-n3
73
- requirement: &70281327922480 !ruby/object:Gem::Requirement
73
+ requirement: &70205083588320 !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: *70281327922480
81
+ version_requirements: *70205083588320
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: rdf-json
84
- requirement: &70281327921720 !ruby/object:Gem::Requirement
84
+ requirement: &70205083587160 !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: *70281327921720
92
+ version_requirements: *70205083587160
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: json-ld
95
- requirement: &70281327920960 !ruby/object:Gem::Requirement
95
+ requirement: &70205083586480 !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: *70281327920960
103
+ version_requirements: *70205083586480
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: guid
106
- requirement: &70281327920460 !ruby/object:Gem::Requirement
106
+ requirement: &70205083584700 !ruby/object:Gem::Requirement
107
107
  none: false
108
108
  requirements:
109
109
  - - ! '>='
@@ -111,7 +111,7 @@ dependencies:
111
111
  version: '0'
112
112
  type: :runtime
113
113
  prerelease: false
114
- version_requirements: *70281327920460
114
+ version_requirements: *70205083584700
115
115
  description: RDF ruby ORM
116
116
  email:
117
117
  - ric@swirrl.com