redlander 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|