Skip to content

Commit ff9d21c

Browse files
committed
Finish 3.0.1
2 parents 2abd569 + b346727 commit ff9d21c

File tree

10 files changed

+199
-64
lines changed

10 files changed

+199
-64
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ doc
1010
coverage
1111
.bundle
1212
/.byebug_history
13+
.ruby-version

README.md

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,70 +25,92 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
2525
## Examples
2626

2727
### Querying a remote SPARQL endpoint
28-
require 'sparql/client'
2928

30-
sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
29+
```ruby
30+
require 'sparql/client'
31+
sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
32+
```
33+
### Querying a remote SPARQL endpoint with a specified default graph
3134

32-
### Querying a `RDF::Repository` instance
35+
```ruby
36+
require 'sparql/client'
37+
sparql = SPARQL::Client.new("http://dbpedia.org/sparql", { :graph => "http://dbpedia.org" })
38+
```
3339

34-
require 'rdf/trig'
35-
repository = RDF::Repository.load("http://example/dataset.trig")
3640

37-
sparql = SPARQL::Client.new(repository)
41+
### Querying a `RDF::Repository` instance
3842

39-
### Executing a boolean query and outputting the result
43+
```ruby
44+
require 'rdf/trig'
45+
repository = RDF::Repository.load("http://example/dataset.trig")
46+
sparql = SPARQL::Client.new(repository)
47+
```
4048

41-
# ASK WHERE { ?s ?p ?o }
42-
result = sparql.ask.whether([:s, :p, :o]).true?
49+
### Executing a boolean query and outputting the result
4350

44-
puts result.inspect #=> true or false
51+
```ruby
52+
# ASK WHERE { ?s ?p ?o }
53+
result = sparql.ask.whether([:s, :p, :o]).true?
54+
puts result.inspect #=> true or false
55+
```
4556

4657
### Executing a tuple query and iterating over the returned solutions
4758

48-
# SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
49-
query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
59+
```ruby
60+
# SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
61+
query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
5062

51-
query.each_solution do |solution|
52-
puts solution.inspect
53-
end
63+
query.each_solution do |solution|
64+
puts solution.inspect
65+
end
66+
```
5467

5568
### Executing a graph query and iterating over the returned statements
5669

57-
# CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10
58-
query = sparql.construct([:s, :p, :o]).where([:s, :p, :o]).limit(10)
5970

60-
query.each_statement do |statement|
61-
puts statement.inspect
62-
end
71+
```ruby
72+
# CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10
73+
query = sparql.construct([:s, :p, :o]).where([:s, :p, :o]).limit(10)
74+
75+
query.each_statement do |statement|
76+
puts statement.inspect
77+
end
78+
```
6379

6480
### Executing an arbitrary textual SPARQL query string
6581

66-
result = sparql.query("ASK WHERE { ?s ?p ?o }")
82+
```ruby
83+
result = sparql.query("ASK WHERE { ?s ?p ?o }")
6784

68-
puts result.inspect #=> true or false
85+
puts result.inspect #=> true or false
86+
```
6987

7088
### Inserting data into a graph
7189

72-
# INSERT DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
73-
data = RDF::Graph.new do |graph|
74-
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
75-
end
76-
sparql.insert_data(data)
90+
```ruby
91+
# INSERT DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
92+
data = RDF::Graph.new do |graph|
93+
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
94+
end
95+
sparql.insert_data(data)
96+
```
7797

7898
### Deleting data from a graph
7999

80-
# DELETE DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
81-
data = RDF::Graph.new do |graph|
82-
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
83-
end
84-
sparql.delete_data(data)
100+
```ruby
101+
# DELETE DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
102+
data = RDF::Graph.new do |graph|
103+
graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
104+
end
105+
sparql.delete_data(data)
106+
```
85107

86108
## Documentation
87109

88-
* {SPARQL::Client}
89-
* {SPARQL::Client::Query}
90-
* {SPARQL::Client::Repository}
91-
* {SPARQL::Client::Update}
110+
* [SPARQL::Client](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client)
111+
* [SPARQL::Client::Query](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Query)
112+
* [SPARQL::Client::Repository](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Repository)
113+
* [SPARQL::Client::Update](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Update)
92114

93115
## Dependencies
94116

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.0
1+
3.0.1

lib/sparql/client.rb

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ServerError < StandardError; end
4040
'*/*;q=0.1'
4141
].join(', ').freeze
4242
GRAPH_ALL = (
43-
RDF::Format.content_types.keys +
43+
RDF::Format.content_types.keys +
4444
['*/*;q=0.1']
4545
).join(', ').freeze
4646

@@ -543,7 +543,7 @@ def parse_rdf_serialization(response, options = {})
543543
if reader = RDF::Reader.for(options)
544544
reader.new(response.body)
545545
else
546-
raise RDF::ReaderError, "no suitable rdf reader was found."
546+
raise RDF::ReaderError, "no RDF reader was found for #{options}."
547547
end
548548
end
549549

@@ -701,8 +701,8 @@ def request(query, headers = {}, &block)
701701
if response.kind_of? Net::HTTPRedirection
702702
response = @http.request(::URI.parse(response['location']), request)
703703
else
704-
return block_given? ? block.call(response) : response
705-
end
704+
return block_given? ? block.call(response) : response
705+
end
706706
end
707707
raise ServerError, "Infinite redirect at #{url}. Redirected more than 10 times."
708708
end
@@ -726,6 +726,7 @@ def request_method(query)
726726
def make_get_request(query, headers = {})
727727
url = self.url.dup
728728
url.query_values = (url.query_values || {}).merge(:query => query.to_s)
729+
set_url_default_graph url unless @options[:graph].nil?
729730
request = Net::HTTP::Get.new(url.request_uri, self.headers.merge(headers))
730731
request
731732
end
@@ -740,23 +741,56 @@ def make_get_request(query, headers = {})
740741
# @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
741742
def make_post_request(query, headers = {})
742743
if @alt_endpoint.nil?
743-
endpoint = url.request_uri
744+
url = self.url.dup
745+
set_url_default_graph url unless @options[:graph].nil?
746+
endpoint = url.request_uri
744747
else
745748
endpoint = @alt_endpoint
746749
end
750+
747751
request = Net::HTTP::Post.new(endpoint, self.headers.merge(headers))
748752
case (self.options[:protocol] || DEFAULT_PROTOCOL).to_s
749753
when '1.1'
750754
request['Content-Type'] = 'application/sparql-' + (@op || :query).to_s
751755
request.body = query.to_s
752756
when '1.0'
753-
request.set_form_data((@op || :query) => query.to_s)
757+
form_data = {(@op || :query) => query.to_s}
758+
form_data.merge!(
759+
{:'default-graph-uri' => @options[:graph]}
760+
) if !@options[:graph].nil? && (@op.eql? :query)
761+
form_data.merge!(
762+
{:'using-graph-uri' => @options[:graph]}
763+
) if !@options[:graph].nil? && (@op.eql? :update)
764+
request.set_form_data(form_data)
754765
else
755766
raise ArgumentError, "unknown SPARQL protocol version: #{self.options[:protocol].inspect}"
756767
end
757768
request
758769
end
759770

771+
##
772+
# Setup url query parameter to use a specified default graph
773+
#
774+
# @see https://www.w3.org/TR/sparql11-protocol/#query-operation
775+
# @see https://www.w3.org/TR/sparql11-protocol/#update-operation
776+
def set_url_default_graph url
777+
if @options[:graph].is_a? Array
778+
graphs = @options[:graph].map {|graph|
779+
CGI::escape(graph)
780+
}
781+
else
782+
graphs = CGI::escape(@options[:graph])
783+
end
784+
case @op
785+
when :query
786+
url.query_values = (url.query_values || {})
787+
.merge(:'default-graph-uri' => graphs)
788+
when :update
789+
url.query_values = (url.query_values || {})
790+
.merge(:'using-graph-uri' => graphs)
791+
end
792+
end
793+
760794
# A query element can be used as a component of a query. It may be initialized with a string, which is wrapped in an appropriate container depending on the type of QueryElement. Implements {#to_s} to property serialize when generating a SPARQL query.
761795
class QueryElement
762796
attr_reader :elements

lib/sparql/client/query.rb

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module SPARQL; class Client
1+
class SPARQL::Client
22
##
33
# A SPARQL query builder.
44
#
@@ -366,16 +366,38 @@ def slice(start, length)
366366
end
367367

368368
##
369-
# @example PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE \{ ?s ?p ?o . \}
370-
# query.select.
371-
# prefix(dc: RDF::URI("http://purl.org/dc/elements/1.1/")).
372-
# prefix(foaf: RDF::URI("http://xmlns.com/foaf/0.1/")).
373-
# where([:s, :p, :o])
369+
# @overload prefix(prefix: uri)
370+
# @example PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE \{ ?s ?p ?o . \}
371+
# query.select.
372+
# prefix(dc: RDF::URI("http://purl.org/dc/elements/1.1/")).
373+
# prefix(foaf: RDF::URI("http://xmlns.com/foaf/0.1/")).
374+
# where([:s, :p, :o])
374375
#
375-
# @return [Query]
376+
# @param [RDF::URI] uri
377+
# @param [Symbol, String] prefix
378+
# @return [Query]
379+
#
380+
# @overload prefix(string)
381+
# @example PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE \{ ?s ?p ?o . \}
382+
# query.select.
383+
# prefix("dc: <http://purl.org/dc/elements/1.1/>").
384+
# prefix("foaf: <http://xmlns.com/foaf/0.1/>").
385+
# where([:s, :p, :o])
386+
#
387+
# @param [string] string
388+
# @return [Query]
376389
# @see http://www.w3.org/TR/sparql11-query/#prefNames
377-
def prefix(string)
378-
(options[:prefixes] ||= []) << string
390+
def prefix(val)
391+
options[:prefixes] ||= []
392+
if val.kind_of? String
393+
options[:prefixes] << val
394+
elsif val.kind_of? Hash
395+
val.each do |k, v|
396+
options[:prefixes] << "#{k}: <#{v}>"
397+
end
398+
else
399+
raise ArgumentError, "prefix must be a kind of String or a Hash"
400+
end
379401
self
380402
end
381403

@@ -823,4 +845,4 @@ def to_s
823845
end
824846
end
825847
end
826-
end; end
848+
end

lib/sparql/client/repository.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module SPARQL; class Client
1+
class SPARQL::Client
22
##
33
# A read-only repository view of a SPARQL endpoint.
44
#
@@ -345,4 +345,4 @@ def insert_statement(statement)
345345
end
346346

347347
end
348-
end; end
348+
end

lib/sparql/client/version.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module SPARQL; class Client
1+
class SPARQL::Client
22
module VERSION
33
FILE = File.expand_path('../../../../VERSION', __FILE__)
44
MAJOR, MINOR, TINY, EXTRA = File.read(FILE).chomp.split('.')
@@ -16,4 +16,4 @@ def self.to_str() STRING end
1616
# @return [Array(Integer, Integer, Integer)]
1717
def self.to_a() [MAJOR, MINOR, TINY] end
1818
end
19-
end; end
19+
end

sparql-client.gemspec

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,7 @@ Gem::Specification.new do |gem|
2020
gem.platform = Gem::Platform::RUBY
2121
gem.files = %w(AUTHORS CREDITS README.md UNLICENSE VERSION) + Dir.glob('lib/**/*.rb')
2222
gem.bindir = %q(bin)
23-
gem.executables = %w()
24-
gem.default_executable = gem.executables.first
2523
gem.require_paths = %w(lib)
26-
gem.extensions = %w()
27-
gem.test_files = %w()
28-
gem.has_rdoc = false
2924

3025
gem.required_ruby_version = '>= 2.2.2'
3126
gem.requirements = []

spec/client_spec.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,51 @@ def response(header)
227227
end
228228
end
229229

230+
context "with multiple Graphs" do
231+
let(:get_graph_client){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', {:method => 'get', :graph => 'http://data.linkedmdb.org/graph1'}) }
232+
let(:post_graph_client10){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', {:method => 'post', :graph => 'http://data.linkedmdb.org/graph1', :protocol => '1.0'}) }
233+
let(:post_graph_client11){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', {:method => 'post', :graph => 'http://data.linkedmdb.org/graph1', :protocol => '1.1'}) }
234+
235+
it "should create 'query via GET' requests" do
236+
WebMock.stub_request(:get, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1&query=SELECT%20%3Fkb%20WHERE%20%7B%20%3Fkb%20%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E%20%22Kevin%20Bacon%22%20.%20%7D').
237+
to_return(:body => '{}', :status => 200, :headers => { 'Content-Type' => 'application/sparql-results+json'})
238+
get_graph_client.query(select_query)
239+
expect(WebMock).to have_requested(:get, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1&query=SELECT%20%3Fkb%20WHERE%20%7B%20%3Fkb%20%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E%20%22Kevin%20Bacon%22%20.%20%7D")
240+
end
241+
242+
it "should create 'query via URL-encoded Post' requests" do
243+
WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
244+
to_return(:body => '{}', :status => 200, :headers => { 'Content-Type' => 'application/sparql-results+json'})
245+
post_graph_client10.query(select_query)
246+
expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
247+
with(:body => "query=SELECT+%3Fkb+WHERE+%7B+%3Fkb+%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E+%22Kevin+Bacon%22+.+%7D&default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1")
248+
end
249+
250+
it "should create 'query via Post directly' requests" do
251+
WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
252+
to_return(:body => '{}', :status => 200, :headers => { 'Content-Type' => 'application/sparql-results+json'})
253+
post_graph_client11.query(select_query)
254+
expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
255+
with(:body => select_query)
256+
end
257+
258+
it "should create requests for 'update via URL-encoded POST'" do
259+
WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
260+
to_return(:body => '{}', :status => 200)
261+
post_graph_client10.update(update_query)
262+
expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
263+
with(:body => "update=DELETE+%7B%3Fs+%3Fp+%3Fo%7D+WHERE+%7B%7D&using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1")
264+
end
265+
266+
it "should create requests for 'update via POST directly'" do
267+
WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
268+
to_return(:body => '{}', :status => 200)
269+
post_graph_client11.update(update_query)
270+
expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
271+
with(:body => update_query)
272+
end
273+
end
274+
230275
context "Error response" do
231276
{
232277
"bad request" => {status: 400, error: SPARQL::Client::MalformedQuery },

0 commit comments

Comments
 (0)