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 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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redlander (0.4.0)
4
+ redlander (0.5.0)
5
5
  ffi (~> 1.1)
6
6
  xml_schema (~> 0.1.0)
7
7
 
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
- (or Redlander::Uri) or use "from_file" method with a local file name (without schema):
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
@@ -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
- # @todo Fix this extremely ineffective (slow) implementation
50
+ # @param [Statement, Hash] pattern (see {#find})
50
51
  # @return [Boolean]
51
- def delete_all
52
- each { |st| delete(st) }
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
- # Size of the model in statements.
78
+ # Checks the existence of statements in the model
79
+ # matching the given criteria
76
80
  #
77
- # @note
78
- # While #count must iterate across all statements in the model,
79
- # {#size} tries to use a more efficient C implementation.
80
- # So {#size} should be preferred to #count in terms of performance.
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} options).
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.rdf_statement : Statement.new(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] options matching pattern made of:
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, options = {})
127
+ def find(scope, pattern = {})
133
128
  case scope
134
129
  when :first
135
- each(options).first
130
+ each(pattern).first
136
131
  when :all
137
- each(options).to_a
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, options)).
139
+ # (Shortcut for {#find}(:first, pattern)).
145
140
  #
146
- # @param [Hash] options (see {#find})
141
+ # @param [Statement, Hash] pattern (see {#find})
147
142
  # @return [Statement, nil]
148
- def first(options = {})
149
- find(:first, options)
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, options)).
148
+ # (Shortcut for {#find}(:all, pattern)).
154
149
  #
155
- # @param [Hash] options (see {#find})
150
+ # @param [Statement, Hash] pattern (see {#find})
156
151
  # @return [Array<Statement>]
157
- def all(options = {})
158
- find(:all, options)
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
@@ -1,4 +1,4 @@
1
1
  module Redlander
2
2
  # Redlander version number
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
@@ -4,21 +4,111 @@ describe Model do
4
4
  let(:model) { described_class.new }
5
5
  subject { model }
6
6
 
7
- describe "statements" do
8
- subject { model.statements }
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
- subject.create(statement_attributes)
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.size.should eql subject.count
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, :size).by(1)
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, :size).by(1)
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, :size).by(1)
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, :size).by(1)
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, :size).by(1)
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, :size).by(-1)
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, :size).from(2).to(0)
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, :size).by(62)
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, :size).by(62)
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, :size).by(57)
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, :size).by(62)
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, :size).by(62)
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, :size).by(62)
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, :size).by(62)
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.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-23 00:00:00.000000000 Z
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: 3614393653179496496
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: 3614393653179496496
129
+ hash: -3720732623496571962
129
130
  requirements: []
130
131
  rubyforge_project:
131
132
  rubygems_version: 1.8.24