redlander 0.4.0 → 0.5.0
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/ChangeLog +8 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +15 -1
- data/lib/redland.rb +23 -0
- data/lib/redlander/model.rb +55 -0
- data/lib/redlander/model_proxy.rb +27 -32
- data/lib/redlander/query/results.rb +118 -0
- data/lib/redlander/version.rb +1 -1
- data/spec/lib/redlander/model_spec.rb +145 -35
- metadata +5 -4
data/ChangeLog
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
redlander (0.5.0)
|
2
|
+
|
3
|
+
* Model#query for queries in SPARQL (and other supported languages)
|
4
|
+
* model.statements.size is obsolete, use model.size or model.statements.count
|
5
|
+
* model.statements.delete_all accepts a pattern to delete only matching statements
|
6
|
+
* added "model.statements.exist?" checker, with a pattern
|
7
|
+
* bugfixes
|
8
|
+
|
1
9
|
redlander (0.4.0)
|
2
10
|
|
3
11
|
* deprecated Parser, Serializer, Storage, Stream and related classes and modules
|
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -59,6 +59,20 @@ You can access the subject, predicate or object of a statement:
|
|
59
59
|
|
60
60
|
Please refer to Redlander::Node API doc for details.
|
61
61
|
|
62
|
+
You can also use different query languages supported by librdf ("SPARQL 1.0" being a default):
|
63
|
+
|
64
|
+
$ m.query("SELECT ?s ?p ?o WHERE {}") # => [{"s" => ..., "p" => ..., "o" => ...}, ...]
|
65
|
+
|
66
|
+
"ASK" queries return true/false, "SELECT" queries return arrays of binding hashes,
|
67
|
+
"CONSTRUCT" queries return an instance of a new memory-based model comprised from
|
68
|
+
the statements constructed by the query.
|
69
|
+
You can also supply a block to Model#query, which is ignored by ASK queries, but
|
70
|
+
yields the statements constructed by CONSTRUCT queries and yields the binding
|
71
|
+
hash for SELECT queries. Binding hash values are instances of Redlander::Node.
|
72
|
+
|
73
|
+
For query options and available query languages refer to Model#query documentation.
|
74
|
+
|
75
|
+
|
62
76
|
== Parsing Input
|
63
77
|
|
64
78
|
You can fill your model with statements by parsing some external sources like plain or streamed data.
|
@@ -72,7 +86,7 @@ If the input is too large, you may prefer streaming it:
|
|
72
86
|
$ m.from(source, :format => "ntriples")
|
73
87
|
|
74
88
|
If you want to get the data from a local file, you can use "file://" schema for your URI
|
75
|
-
|
89
|
+
or use "from_file" method with a local file name (without schema):
|
76
90
|
|
77
91
|
$ m.from_file("../data.ttl", :format => "turtle")
|
78
92
|
|
data/lib/redland.rb
CHANGED
@@ -27,10 +27,12 @@ module Redland
|
|
27
27
|
attach_function :librdf_model_size, [:pointer], :int
|
28
28
|
attach_function :librdf_model_find_statements, [:pointer, :pointer], :pointer
|
29
29
|
attach_function :librdf_model_add_statement, [:pointer, :pointer], :int
|
30
|
+
attach_function :librdf_model_add_statements, [:pointer, :pointer], :int
|
30
31
|
attach_function :librdf_model_remove_statement, [:pointer, :pointer], :int
|
31
32
|
attach_function :librdf_model_transaction_start, [:pointer], :int
|
32
33
|
attach_function :librdf_model_transaction_commit, [:pointer], :int
|
33
34
|
attach_function :librdf_model_transaction_rollback, [:pointer], :int
|
35
|
+
attach_function :librdf_model_query_execute, [:pointer, :pointer], :pointer
|
34
36
|
|
35
37
|
# Statement
|
36
38
|
attach_function :librdf_free_statement, [:pointer], :void
|
@@ -85,4 +87,25 @@ module Redland
|
|
85
87
|
attach_function :librdf_free_uri, [:pointer], :void
|
86
88
|
attach_function :librdf_uri_to_string, [:pointer], :string
|
87
89
|
attach_function :librdf_uri_equals, [:pointer, :pointer], :int
|
90
|
+
|
91
|
+
# Query
|
92
|
+
attach_function :librdf_new_query, [:pointer, :string, :pointer, :string, :pointer], :pointer
|
93
|
+
attach_function :librdf_free_query, [:pointer], :void
|
94
|
+
attach_function :librdf_query_get_limit, [:pointer], :int
|
95
|
+
attach_function :librdf_query_set_limit, [:pointer, :int], :int
|
96
|
+
attach_function :librdf_query_get_offset, [:pointer], :int
|
97
|
+
attach_function :librdf_query_set_limit, [:pointer, :int], :int
|
98
|
+
attach_function :librdf_query_results_is_bindings, [:pointer], :int
|
99
|
+
attach_function :librdf_query_results_is_boolean, [:pointer], :int
|
100
|
+
attach_function :librdf_query_results_is_graph, [:pointer], :int
|
101
|
+
attach_function :librdf_query_results_is_syntax, [:pointer], :int
|
102
|
+
attach_function :librdf_query_results_get_binding_name, [:pointer, :int], :string
|
103
|
+
attach_function :librdf_query_results_get_binding_value, [:pointer, :int], :pointer
|
104
|
+
attach_function :librdf_query_results_get_binding_value_by_name, [:pointer, :string], :pointer
|
105
|
+
attach_function :librdf_query_results_get_bindings_count, [:pointer], :int
|
106
|
+
attach_function :librdf_query_results_get_boolean, [:pointer], :int
|
107
|
+
attach_function :librdf_query_results_as_stream, [:pointer], :pointer
|
108
|
+
attach_function :librdf_query_results_next, [:pointer], :int
|
109
|
+
attach_function :librdf_query_results_finished, [:pointer], :int
|
110
|
+
attach_function :librdf_free_query_results, [:pointer], :void
|
88
111
|
end
|
data/lib/redlander/model.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'redlander/parsing'
|
2
2
|
require 'redlander/serializing'
|
3
3
|
require 'redlander/model_proxy'
|
4
|
+
require "redlander/query/results"
|
4
5
|
|
5
6
|
module Redlander
|
6
7
|
# The core object incorporating the repository of RDF statements.
|
@@ -66,6 +67,60 @@ module Redlander
|
|
66
67
|
ModelProxy.new(self)
|
67
68
|
end
|
68
69
|
|
70
|
+
# Size of the model, in statements.
|
71
|
+
#
|
72
|
+
# @return [Fixnum]
|
73
|
+
def size
|
74
|
+
s = Redland.librdf_model_size(@rdf_model)
|
75
|
+
s < 0 ? statements.count : s
|
76
|
+
end
|
77
|
+
|
78
|
+
# Query the model RDF graph using a query language
|
79
|
+
#
|
80
|
+
# @param [String] q the text of the query
|
81
|
+
# @param [Hash<Symbol => [String, URI]>] options options for the query
|
82
|
+
# @option options [String] :language language of the query, one of:
|
83
|
+
# - "sparql10" SPARQL 1.0 W3C RDF Query Language (default)
|
84
|
+
# - "sparql" SPARQL 1.1 (DRAFT) Query and Update Languages
|
85
|
+
# - "sparql11-query" SPARQL 1.1 (DRAFT) Query Language
|
86
|
+
# - "sparql11-update" SPARQL 1.1 (DRAFT) Update Language
|
87
|
+
# - "laqrs" LAQRS adds to Querying RDF in SPARQL
|
88
|
+
# - "rdql" RDF Data Query Language (RDQL)
|
89
|
+
# @option options [String] :language_uri URI of the query language, if applicable
|
90
|
+
# @option options [String] :base_uri base URI of the query, if applicable
|
91
|
+
# @return [void]
|
92
|
+
# @note
|
93
|
+
# The returned value is determined by the type of the query:
|
94
|
+
# - [Boolean] for SPARQL ASK queries (ignores block, if given)
|
95
|
+
# - [Redlander::Model] for SPARQL CONSTRUCT queries
|
96
|
+
# if given a block, yields the constructed statements to it instead
|
97
|
+
# - [Array<Hash>] for SPARQL SELECT queries
|
98
|
+
# where hash values are Redlander::Node instances;
|
99
|
+
# if given a block, yields each binding hash to it
|
100
|
+
# - nil, if query fails
|
101
|
+
# @raise [RedlandError] if fails to create a query
|
102
|
+
def query(q, options = {})
|
103
|
+
query = Query::Results.new(q, options)
|
104
|
+
query.process(self)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Merge statements from another model
|
108
|
+
# (duplicates and invalid statements are skipped)
|
109
|
+
#
|
110
|
+
# @param [Redlander::Model] model
|
111
|
+
# @return [self]
|
112
|
+
def merge(model)
|
113
|
+
rdf_stream = Redland.librdf_model_as_stream(model.rdf_model)
|
114
|
+
raise RedlandError, "Failed to convert model to a stream" if rdf_stream.null?
|
115
|
+
|
116
|
+
begin
|
117
|
+
Redland.librdf_model_add_statements(@rdf_model, rdf_stream)
|
118
|
+
self
|
119
|
+
ensure
|
120
|
+
Redland.librdf_free_stream(rdf_stream)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
69
124
|
# Wrap changes to the given model in a transaction.
|
70
125
|
# If an exception is raised in the block, the transaction is rolled back.
|
71
126
|
#
|
@@ -44,12 +44,15 @@ module Redlander
|
|
44
44
|
Redland.librdf_model_remove_statement(@model.rdf_model, statement.rdf_statement).zero?
|
45
45
|
end
|
46
46
|
|
47
|
-
# Delete all statements from the model
|
47
|
+
# Delete all statements from the model,
|
48
|
+
# matching the given pattern
|
48
49
|
#
|
49
|
-
# @
|
50
|
+
# @param [Statement, Hash] pattern (see {#find})
|
50
51
|
# @return [Boolean]
|
51
|
-
def delete_all
|
52
|
-
|
52
|
+
def delete_all(pattern = {})
|
53
|
+
result = true
|
54
|
+
each(pattern) { |st| result &&= delete(st) }
|
55
|
+
result
|
53
56
|
end
|
54
57
|
|
55
58
|
# Create a statement and add it to the model.
|
@@ -72,21 +75,13 @@ module Redlander
|
|
72
75
|
size.zero?
|
73
76
|
end
|
74
77
|
|
75
|
-
#
|
78
|
+
# Checks the existence of statements in the model
|
79
|
+
# matching the given criteria
|
76
80
|
#
|
77
|
-
# @
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
# However, for non-countable storages, {#size} falls back to
|
82
|
-
# using #count. Also, {#size} is not available for enumerables
|
83
|
-
# (e.g. produced from {#each} (without a block) or otherwise) and
|
84
|
-
# thus cannot be used to count "filtered" results.
|
85
|
-
#
|
86
|
-
# @return [Fixnum]
|
87
|
-
def size
|
88
|
-
s = Redland.librdf_model_size(@model.rdf_model)
|
89
|
-
s < 0 ? count : s
|
81
|
+
# @param [Hash, Statement] pattern (see {#find})
|
82
|
+
# @return [Boolean]
|
83
|
+
def exist?(pattern)
|
84
|
+
!first(pattern).nil?
|
90
85
|
end
|
91
86
|
|
92
87
|
# Enumerate (and filter) model statements.
|
@@ -94,7 +89,7 @@ module Redlander
|
|
94
89
|
#
|
95
90
|
# @param [Statement, Hash, void] args
|
96
91
|
# if given Statement or Hash, filter the model statements
|
97
|
-
# according to the specified pattern (see {#find}
|
92
|
+
# according to the specified pattern (see {#find} pattern).
|
98
93
|
# @yieldparam [Statement]
|
99
94
|
# @return [void]
|
100
95
|
def each(*args)
|
@@ -103,7 +98,7 @@ module Redlander
|
|
103
98
|
if args.empty?
|
104
99
|
Redland.librdf_model_as_stream(@model.rdf_model)
|
105
100
|
else
|
106
|
-
pattern = args.first.is_a?(Statement) ? args.first
|
101
|
+
pattern = args.first.is_a?(Statement) ? args.first : Statement.new(args.first)
|
107
102
|
Redland.librdf_model_find_statements(@model.rdf_model, pattern.rdf_statement)
|
108
103
|
end
|
109
104
|
raise RedlandError, "Failed to create a new stream" if rdf_stream.null?
|
@@ -125,37 +120,37 @@ module Redlander
|
|
125
120
|
# Find statements satisfying the given criteria.
|
126
121
|
#
|
127
122
|
# @param [:first, :all] scope find just one or all matches
|
128
|
-
# @param [Hash, Statement]
|
123
|
+
# @param [Hash, Statement] pattern matching pattern made of:
|
129
124
|
# - Hash with :subject, :predicate or :object nodes, or
|
130
125
|
# - "patternized" Statement (nil nodes are matching anything).
|
131
126
|
# @return [Statement, Array, nil]
|
132
|
-
def find(scope,
|
127
|
+
def find(scope, pattern = {})
|
133
128
|
case scope
|
134
129
|
when :first
|
135
|
-
each(
|
130
|
+
each(pattern).first
|
136
131
|
when :all
|
137
|
-
each(
|
132
|
+
each(pattern).to_a
|
138
133
|
else
|
139
134
|
raise RedlandError, "Invalid search scope '#{scope}' specified."
|
140
135
|
end
|
141
136
|
end
|
142
137
|
|
143
138
|
# Find a first statement matching the given criteria.
|
144
|
-
# (Shortcut for {#find}(:first,
|
139
|
+
# (Shortcut for {#find}(:first, pattern)).
|
145
140
|
#
|
146
|
-
# @param [Hash]
|
141
|
+
# @param [Statement, Hash] pattern (see {#find})
|
147
142
|
# @return [Statement, nil]
|
148
|
-
def first(
|
149
|
-
find(:first,
|
143
|
+
def first(pattern = {})
|
144
|
+
find(:first, pattern)
|
150
145
|
end
|
151
146
|
|
152
147
|
# Find all statements matching the given criteria.
|
153
|
-
# (Shortcut for {#find}(:all,
|
148
|
+
# (Shortcut for {#find}(:all, pattern)).
|
154
149
|
#
|
155
|
-
# @param [Hash]
|
150
|
+
# @param [Statement, Hash] pattern (see {#find})
|
156
151
|
# @return [Array<Statement>]
|
157
|
-
def all(
|
158
|
-
find(:all,
|
152
|
+
def all(pattern = {})
|
153
|
+
find(:all, pattern)
|
159
154
|
end
|
160
155
|
end
|
161
156
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Redlander
|
2
|
+
module Query
|
3
|
+
# @api private
|
4
|
+
class Results
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# (see Model#query)
|
8
|
+
def initialize(q, options = {})
|
9
|
+
language = options[:language] || "sparql10"
|
10
|
+
language_uri = options[:language_uri] && options[:language_uri].to_s
|
11
|
+
base_uri = options[:base_uri] && options[:base_uri].to_s
|
12
|
+
|
13
|
+
@rdf_query = Redland.librdf_new_query(Redlander.rdf_world, language, language_uri, q, base_uri)
|
14
|
+
raise RedlandError, "Failed to create a #{language.upcase} query from '#{q}'" if @rdf_query.null?
|
15
|
+
|
16
|
+
ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_query(@rdf_query) })
|
17
|
+
end
|
18
|
+
|
19
|
+
def process(model)
|
20
|
+
@rdf_results = Redland.librdf_model_query_execute(model.rdf_model, @rdf_query)
|
21
|
+
|
22
|
+
if @rdf_results.null?
|
23
|
+
return nil
|
24
|
+
else
|
25
|
+
case
|
26
|
+
when bindings?
|
27
|
+
if block_given?
|
28
|
+
each { yield process_bindings }
|
29
|
+
else
|
30
|
+
map { process_bindings }
|
31
|
+
end
|
32
|
+
when boolean?
|
33
|
+
process_boolean
|
34
|
+
when graph?
|
35
|
+
if block_given?
|
36
|
+
process_graph { |statement| yield statement }
|
37
|
+
else
|
38
|
+
process_graph
|
39
|
+
end
|
40
|
+
when syntax?
|
41
|
+
process_syntax
|
42
|
+
else
|
43
|
+
raise RedlandError, "Cannot determine the type of query results"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
ensure
|
47
|
+
Redland.librdf_free_query_results(@rdf_results)
|
48
|
+
end
|
49
|
+
|
50
|
+
def each
|
51
|
+
if block_given?
|
52
|
+
while Redland.librdf_query_results_finished(@rdf_results).zero?
|
53
|
+
yield self
|
54
|
+
Redland.librdf_query_results_next(@rdf_results)
|
55
|
+
end
|
56
|
+
else
|
57
|
+
enum_for(:each)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def bindings?
|
62
|
+
!Redland.librdf_query_results_is_bindings(@rdf_results).zero?
|
63
|
+
end
|
64
|
+
|
65
|
+
def boolean?
|
66
|
+
!Redland.librdf_query_results_is_boolean(@rdf_results).zero?
|
67
|
+
end
|
68
|
+
|
69
|
+
def graph?
|
70
|
+
!Redland.librdf_query_results_is_graph(@rdf_results).zero?
|
71
|
+
end
|
72
|
+
|
73
|
+
def syntax?
|
74
|
+
!Redland.librdf_query_results_is_syntax(@rdf_results).zero?
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def process_bindings
|
80
|
+
{}.tap do |bindings|
|
81
|
+
n = Redland.librdf_query_results_get_bindings_count(@rdf_results)
|
82
|
+
while n > 0
|
83
|
+
name = Redland.librdf_query_results_get_binding_name(@rdf_results, n-1)
|
84
|
+
value = Redland.librdf_query_results_get_binding_value(@rdf_results, n-1)
|
85
|
+
bindings[name] = Node.new(value) unless value.null?
|
86
|
+
n -= 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def process_boolean
|
92
|
+
value = Redland.librdf_query_results_get_boolean(@rdf_results)
|
93
|
+
return value >= 0 ? !value.zero? : nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def process_graph
|
97
|
+
rdf_stream = Redland.librdf_query_results_as_stream(@rdf_results)
|
98
|
+
if block_given?
|
99
|
+
while Redland.librdf_stream_end(rdf_stream).zero?
|
100
|
+
statement = Statement.new(Redland.librdf_stream_get_object(rdf_stream))
|
101
|
+
yield statement
|
102
|
+
Redland.librdf_stream_next(rdf_stream)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
Model.new.tap do |model|
|
106
|
+
Redland.librdf_model_add_statements(model.rdf_model, rdf_stream)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
ensure
|
110
|
+
Redland.librdf_free_stream(rdf_stream)
|
111
|
+
end
|
112
|
+
|
113
|
+
def process_syntax
|
114
|
+
raise NotImplementedError, "Don't know how to handle syntax type results"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/redlander/version.rb
CHANGED
@@ -4,21 +4,111 @@ describe Model do
|
|
4
4
|
let(:model) { described_class.new }
|
5
5
|
subject { model }
|
6
6
|
|
7
|
-
describe "
|
8
|
-
subject { model.
|
9
|
-
|
10
|
-
it { should be_an_instance_of(ModelProxy) }
|
7
|
+
describe "size" do
|
8
|
+
subject { model.size }
|
11
9
|
|
12
10
|
context "for a non-countable storage" do
|
13
11
|
before do
|
14
|
-
|
12
|
+
model.statements.create(statement_attributes)
|
15
13
|
Redland.stub(:librdf_model_size => -1)
|
16
14
|
end
|
17
15
|
|
18
16
|
it "should return size derived from count" do
|
19
|
-
subject.
|
17
|
+
subject.should eql model.statements.count
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "query" do
|
23
|
+
before { model.from_file(Redlander.fixture_path("doap.ttl"), :format => "turtle") }
|
24
|
+
subject { model.query(q) }
|
25
|
+
|
26
|
+
describe "SPARQL" do
|
27
|
+
describe "SELECT" do
|
28
|
+
let(:q) { "PREFIX doap: <http://usefulinc.com/ns/doap#> SELECT ?name WHERE { <http://rubygems.org/gems/rdf> doap:name ?name }" }
|
29
|
+
|
30
|
+
it { should be_a Enumerable }
|
31
|
+
|
32
|
+
it "should return an array of binding hashes" do
|
33
|
+
expect(subject.size).to eql 1
|
34
|
+
expect(subject.first["name"]).to be_a Redlander::Node
|
35
|
+
expect(subject.first["name"].value).to eql "RDF.rb"
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with a block" do
|
39
|
+
it "should yield a binding hash" do
|
40
|
+
subject do |binding|
|
41
|
+
expect(binding).to be_a Hash
|
42
|
+
expect(binding["name"]).to be_a Redlander::Node
|
43
|
+
expect(binding["name"].value).to eql "RDF.rb"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "ASK" do
|
50
|
+
let(:q) { "PREFIX doap: <http://usefulinc.com/ns/doap#> ASK { <http://rubygems.org/gems/rdf> doap:homepage <http://rdf.rubyforge.org/> }" }
|
51
|
+
|
52
|
+
it { should be_true }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "CONSTRUCT" do
|
56
|
+
let(:q) { "PREFIX doap: <http://usefulinc.com/ns/doap#> CONSTRUCT { ?project doap:framework 'RDF'^^<http://www.w3.org/2001/XMLSchema#string> } WHERE { ?project a doap:Project }" }
|
57
|
+
|
58
|
+
it { should be_a Redlander::Model }
|
59
|
+
|
60
|
+
it "should return a model made from the constructed statements" do
|
61
|
+
statement = Redlander::Statement.new(:subject => URI("http://rubygems.org/gems/rdf"),
|
62
|
+
:predicate => URI("http://usefulinc.com/ns/doap#framework"),
|
63
|
+
:object => "RDF")
|
64
|
+
expect(subject.statements.count).to eql 1
|
65
|
+
expect(subject.statements.exist?(statement)).to be_true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "DESCRIBE" do
|
70
|
+
let(:q) { "PREFIX doap: <http://usefulinc.com/ns/doap#> DESCRIBE ?gem WHERE { ?gem a doap:Project }" }
|
71
|
+
|
72
|
+
it { pending "Not implemented. See: http://bugs.librdf.org/mantis/view.php?id=135" }
|
20
73
|
end
|
21
74
|
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "merge" do
|
78
|
+
before do
|
79
|
+
@model2 = Redlander::Model.new
|
80
|
+
@model3 = Redlander::Model.new
|
81
|
+
@statement1 = Redlander::Statement.new(:subject => URI("http://rubygems.org/gems/rdf"),
|
82
|
+
:predicate => URI("http://usefulinc.com/ns/doap#framework"),
|
83
|
+
:object => "RDF")
|
84
|
+
model.statements.add(@statement1)
|
85
|
+
@statement2 = Redlander::Statement.new(:subject => URI("http://rubygems.org/gems/rdfs"),
|
86
|
+
:predicate => URI("http://usefulinc.com/ns/doap#framework"),
|
87
|
+
:object => "RDFS")
|
88
|
+
@model2.statements.add(@statement2)
|
89
|
+
@model3.statements.add(@statement1)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should return model" do
|
93
|
+
expect(model.merge(@model2)).to eql model
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should add different model statements" do
|
97
|
+
expect { model.merge(@model2) }.to change(model, :size).by(1)
|
98
|
+
expect(model.statements).to include(@statement1)
|
99
|
+
expect(model.statements).to include(@statement2)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should add same model statements" do
|
103
|
+
expect { model.merge(@model3) }.not_to change(model, :size)
|
104
|
+
expect(model.statements).to include(@statement1)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "statements" do
|
109
|
+
subject { model.statements }
|
110
|
+
|
111
|
+
it { should be_an_instance_of(ModelProxy) }
|
22
112
|
|
23
113
|
context "when enumerated" do
|
24
114
|
context "without a block" do
|
@@ -36,7 +126,7 @@ describe Model do
|
|
36
126
|
it "should be iterated over" do
|
37
127
|
expect {
|
38
128
|
subject.each { |s| @statements << s }
|
39
|
-
}.to change(@statements, :
|
129
|
+
}.to change(@statements, :count).by(1)
|
40
130
|
expect(@statements).to include @statement
|
41
131
|
end
|
42
132
|
end
|
@@ -44,7 +134,6 @@ describe Model do
|
|
44
134
|
|
45
135
|
context "when searched" do
|
46
136
|
subject { model.statements.find(:first, @conditions) }
|
47
|
-
|
48
137
|
before { @statement = model.statements.create(statement_attributes) }
|
49
138
|
|
50
139
|
context "with empty conditions" do
|
@@ -66,16 +155,33 @@ describe Model do
|
|
66
155
|
end
|
67
156
|
end
|
68
157
|
|
158
|
+
context "when checked for existance" do
|
159
|
+
subject { model.statements.exist?(@conditions) }
|
160
|
+
before { @statement = model.statements.create(statement_attributes) }
|
161
|
+
|
162
|
+
context "with matching conditions" do
|
163
|
+
before { @conditions = {:object => @statement.object} }
|
164
|
+
|
165
|
+
it { should be_true }
|
166
|
+
end
|
167
|
+
|
168
|
+
context "with non-matching conditions" do
|
169
|
+
before { @conditions = {:object => "another object"} }
|
170
|
+
|
171
|
+
it { should be_false }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
69
175
|
context "when adding" do
|
70
176
|
context "via #create" do
|
71
177
|
it "should be created in the model" do
|
72
|
-
expect { subject.create(statement_attributes) }.to change(subject, :
|
178
|
+
expect { subject.create(statement_attributes) }.to change(subject, :count).by(1)
|
73
179
|
end
|
74
180
|
|
75
181
|
it "should not add duplicate statements" do
|
76
182
|
expect {
|
77
183
|
2.times { subject.create(statement_attributes) }
|
78
|
-
}.to change(subject, :
|
184
|
+
}.to change(subject, :count).by(1)
|
79
185
|
end
|
80
186
|
end
|
81
187
|
|
@@ -83,14 +189,14 @@ describe Model do
|
|
83
189
|
before { @statement = Statement.new(statement_attributes) }
|
84
190
|
|
85
191
|
it "should be added to the model" do
|
86
|
-
expect { subject.add(@statement) }.to change(subject, :
|
192
|
+
expect { subject.add(@statement) }.to change(subject, :count).by(1)
|
87
193
|
subject.should include(@statement)
|
88
194
|
end
|
89
195
|
|
90
196
|
it "should not add duplicate statements" do
|
91
197
|
expect {
|
92
198
|
2.times { subject.add(@statement) }
|
93
|
-
}.to change(subject, :
|
199
|
+
}.to change(subject, :count).by(1)
|
94
200
|
end
|
95
201
|
end
|
96
202
|
end
|
@@ -99,32 +205,22 @@ describe Model do
|
|
99
205
|
before { @statement = subject.create(statement_attributes) }
|
100
206
|
|
101
207
|
it "should be removed from the model" do
|
102
|
-
expect { subject.delete(@statement) }.to change(subject, :
|
208
|
+
expect { subject.delete(@statement) }.to change(subject, :count).by(-1)
|
103
209
|
subject.should_not include(@statement)
|
104
210
|
end
|
105
211
|
|
106
212
|
describe "all statements" do
|
107
213
|
before { subject.create(statement_attributes.merge(:object => "another one")) }
|
108
214
|
|
215
|
+
it "should selectively delete statements" do
|
216
|
+
expect { subject.delete_all(:object => "another one") }.to change(subject, :count).by(-1)
|
217
|
+
end
|
218
|
+
|
109
219
|
it "should completely wipe the model" do
|
110
|
-
expect { subject.delete_all }.to change(subject, :
|
220
|
+
expect { subject.delete_all }.to change(subject, :count).from(2).to(0)
|
111
221
|
end
|
112
222
|
end
|
113
223
|
end
|
114
|
-
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
def statement_attributes
|
119
|
-
s = URI.parse('http://example.com/concepts#subject')
|
120
|
-
p = URI.parse('http://example.com/concepts#label')
|
121
|
-
o = "subject!"
|
122
|
-
{
|
123
|
-
:subject => s,
|
124
|
-
:predicate => p,
|
125
|
-
:object => o
|
126
|
-
}
|
127
|
-
end
|
128
224
|
end
|
129
225
|
|
130
226
|
describe "serialization" do
|
@@ -200,13 +296,13 @@ describe Model do
|
|
200
296
|
it "should parse from string" do
|
201
297
|
expect {
|
202
298
|
subject.from_rdfxml File.read(@filename), :base_uri => "http://rubygems.org/gems/rdf"
|
203
|
-
}.to change(subject.statements, :
|
299
|
+
}.to change(subject.statements, :count).by(62)
|
204
300
|
end
|
205
301
|
|
206
302
|
it "should parse from URI/file" do
|
207
303
|
expect {
|
208
304
|
subject.from_rdfxml URI("file://" + @filename), :base_uri => "http://rubygems.org/gems/rdf"
|
209
|
-
}.to change(subject.statements, :
|
305
|
+
}.to change(subject.statements, :count).by(62)
|
210
306
|
end
|
211
307
|
|
212
308
|
it "should filter statements" do
|
@@ -215,7 +311,7 @@ describe Model do
|
|
215
311
|
subject.from_rdfxml URI("file://" + @filename), :base_uri => "http://rubygems.org/gems/rdf" do |st|
|
216
312
|
st.object.resource? ? st.object.uri != filter_object : true
|
217
313
|
end
|
218
|
-
}.to change(subject.statements, :
|
314
|
+
}.to change(subject.statements, :count).by(57)
|
219
315
|
end
|
220
316
|
end
|
221
317
|
|
@@ -225,13 +321,13 @@ describe Model do
|
|
225
321
|
it "should parse from string" do
|
226
322
|
expect {
|
227
323
|
subject.from_ntriples File.read(@filename)
|
228
|
-
}.to change(subject.statements, :
|
324
|
+
}.to change(subject.statements, :count).by(62)
|
229
325
|
end
|
230
326
|
|
231
327
|
it "should parse from URI/file" do
|
232
328
|
expect {
|
233
329
|
subject.from_ntriples URI("file://" + @filename)
|
234
|
-
}.to change(subject.statements, :
|
330
|
+
}.to change(subject.statements, :count).by(62)
|
235
331
|
end
|
236
332
|
end
|
237
333
|
|
@@ -241,13 +337,13 @@ describe Model do
|
|
241
337
|
it "should parse from string" do
|
242
338
|
expect {
|
243
339
|
subject.from_turtle File.read(@filename), :base_uri => "http://rubygems.org/gems/rdf"
|
244
|
-
}.to change(subject.statements, :
|
340
|
+
}.to change(subject.statements, :count).by(62)
|
245
341
|
end
|
246
342
|
|
247
343
|
it "should parse from URI/file" do
|
248
344
|
expect {
|
249
345
|
subject.from_turtle URI("file://" + @filename), :base_uri => "http://rubygems.org/gems/rdf"
|
250
|
-
}.to change(subject.statements, :
|
346
|
+
}.to change(subject.statements, :count).by(62)
|
251
347
|
end
|
252
348
|
end
|
253
349
|
end
|
@@ -301,4 +397,18 @@ describe Model do
|
|
301
397
|
end
|
302
398
|
end
|
303
399
|
end
|
400
|
+
|
401
|
+
|
402
|
+
private
|
403
|
+
|
404
|
+
def statement_attributes
|
405
|
+
s = URI.parse('http://example.com/concepts#subject')
|
406
|
+
p = URI.parse('http://example.com/concepts#label')
|
407
|
+
o = "subject!"
|
408
|
+
{
|
409
|
+
:subject => s,
|
410
|
+
:predicate => p,
|
411
|
+
:object => o
|
412
|
+
}
|
413
|
+
end
|
304
414
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redlander
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: xml_schema
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- lib/redlander/model_proxy.rb
|
88
88
|
- lib/redlander/node.rb
|
89
89
|
- lib/redlander/parsing.rb
|
90
|
+
- lib/redlander/query/results.rb
|
90
91
|
- lib/redlander/serializing.rb
|
91
92
|
- lib/redlander/statement.rb
|
92
93
|
- lib/redlander/uri.rb
|
@@ -116,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
117
|
version: '0'
|
117
118
|
segments:
|
118
119
|
- 0
|
119
|
-
hash:
|
120
|
+
hash: -3720732623496571962
|
120
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
122
|
none: false
|
122
123
|
requirements:
|
@@ -125,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
126
|
version: '0'
|
126
127
|
segments:
|
127
128
|
- 0
|
128
|
-
hash:
|
129
|
+
hash: -3720732623496571962
|
129
130
|
requirements: []
|
130
131
|
rubyforge_project:
|
131
132
|
rubygems_version: 1.8.24
|