Skip to content

Commit

Permalink
Finish 3.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Jan 8, 2020
2 parents f06f671 + 484303a commit a24805a
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -12,3 +12,5 @@ Gemfile.lock
benchmark/
/.byebug_history
/coverage/
\#*\#
.\#*
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -10,7 +10,7 @@ group :develop do
gem "rdf-vocab", git: "https://github.com/ruby-rdf/rdf-vocab", branch: "develop"
gem "rdf-xsd", git: "https://github.com/ruby-rdf/rdf-xsd", branch: "develop"

gem "ebnf", git: "https://github.com/gkellogg/ebnf", branch: "develop"
gem "ebnf", git: "https://github.com/dryruby/ebnf", branch: "develop"
gem "sxp", git: "https://github.com/dryruby/sxp", branch: "develop"

gem 'rest-client-components'
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
3.1.0
3.1.1
97 changes: 79 additions & 18 deletions lib/rdf/changeset.rb
Expand Up @@ -31,10 +31,11 @@ module RDF
#
# @since 2.0.0
class Changeset
include RDF::Mutable
# include RDF::Mutable
include RDF::Util::Coercions

##
# Applies a changeset to the given mutable RDF::Enumerable .
# Applies a changeset to the given {RDF::Mutable} object.
#
# @param [RDF::Mutable] mutable
# @param [Hash{Symbol => Object}] options
Expand Down Expand Up @@ -98,6 +99,24 @@ def readable?
false
end

##
# Returns `false` as changesets are not {RDF::Writable}.
#
# @return [Boolean]
# @see RDF::Writable#writable?
def writable?
false
end

##
# Returns `false` as changesets are not {RDF::Mutable}.
#
# @return [Boolean]
# @see RDF::Mutable#mutable?
def mutable?
false
end

##
# Applies this changeset to the given mutable RDF::Enumerable.
#
Expand Down Expand Up @@ -127,35 +146,77 @@ def inspect

##
# Outputs a developer-friendly representation of this changeset to
# `stderr`.
# `$stderr`.
#
# @return [void]
def inspect!
$stderr.puts(self.inspect)
end

protected

##
# Appends an RDF statement to the sequence to insert when applied.
# Returns the sum of both the `inserts` and `deletes` counts.
#
# @param [RDF::Statement] statement
# @return [void]
# @see RDF::Writable#insert_statement
def insert_statement(statement)
self.inserts << statement
# @return [Integer]
def count
inserts.count + deletes.count
end

# Append statements to `inserts`. Statements _should_ be constant
# as variable statements will at best be ignored or at worst raise
# an error when applied.
#
# @param statements [Enumerable, RDF::Statement] Some statements
# @return [self]
def insert(*statements)
coerce_statements(statements) do |stmts|
append_statements :inserts, stmts
end

self
end
alias_method :insert!, :insert
alias_method :<<, :insert

# Append statements to `deletes`. Statements _may_ contain
# variables, although support will depend on the {RDF::Mutable}
# target.
#
# @param statements [Enumerable, RDF::Statement] Some statements
# @return [self]
def delete(*statements)
coerce_statements(statements) do |stmts|
append_statements :deletes, stmts
end

self
end
alias_method :delete!, :delete
alias_method :>>, :delete

private

##
# Appends an RDF statement to the sequence to delete when applied.
# Append statements to the appropriate target. This is a little
# shim to go in between the other shim and the target.
#
# @param [RDF::Statement] statement
# @return [void]
# @see RDF::Mutable#delete_statement
def delete_statement(statement)
self.deletes << statement
# @param target [Symbol] the method to send
# @param arg [Enumerable, RDF::Statement]
#
def append_statements(target, arg)
# coerce to an enumerator
stmts = case
when arg.is_a?(RDF::Statement)
[arg]
when arg.respond_to?(:each_statement)
arg.each_statement
when arg.respond_to?(:each)
arg
else
raise ArgumentError, "Invalid statement: #{arg.class}"
end

stmts.each { |s| send(target) << s }
end

undef_method :load, :update, :clear
end # Changeset
end # RDF
16 changes: 3 additions & 13 deletions lib/rdf/mixin/mutable.rb
Expand Up @@ -9,6 +9,7 @@ module Mutable
extend RDF::Util::Aliasing::LateBound
include RDF::Readable
include RDF::Writable
include RDF::Util::Coercions

##
# Returns `true` if `self` is mutable.
Expand Down Expand Up @@ -154,20 +155,9 @@ def update(*statements)
def delete(*statements)
raise TypeError.new("#{self} is immutable") if immutable?

statements.map! do |value|
case
when value.respond_to?(:each_statement)
delete_statements(value)
nil
when (statement = Statement.from(value)).constant?
statement
else
delete_statements(query(value))
nil
end
coerce_statements(statements, query: true, constant: true) do |value|
delete_statements(value)
end
statements.compact!
delete_statements(statements) unless statements.empty?

return self
end
Expand Down
16 changes: 2 additions & 14 deletions lib/rdf/mixin/writable.rb
Expand Up @@ -7,6 +7,7 @@ module RDF
# @see RDF::Repository
module Writable
extend RDF::Util::Aliasing::LateBound
include RDF::Util::Coercions

##
# Returns `true` if `self` is writable.
Expand Down Expand Up @@ -58,26 +59,13 @@ def <<(data)
# @param [Enumerable<RDF::Statement>] statements
# @return [self]
def insert(*statements)
statements.map! do |value|
case
when value.respond_to?(:each_statement)
insert_statements(value)
nil
when (statement = Statement.from(value))
statement
else
raise ArgumentError.new("not a valid statement: #{value.inspect}")
end
end
statements.compact!
insert_statements(statements) unless statements.empty?
coerce_statements(statements) { |value| insert_statements value }

return self
end
alias_method :insert!, :insert

protected

##
# Inserts statements from the given RDF reader into the underlying
# storage or output stream.
Expand Down
9 changes: 8 additions & 1 deletion lib/rdf/repository.rb
Expand Up @@ -340,7 +340,14 @@ def each_statement(&block)
# @see Mutable#apply_changeset
def apply_changeset(changeset)
data = @data
changeset.deletes.each { |del| data = delete_from(data, del) }
changeset.deletes.each do |del|
if del.constant?
data = delete_from(data, del)
else
# we need this condition to handle wildcard statements
query_pattern(del) { |stmt| data = delete_from(data, stmt) }
end
end
changeset.inserts.each { |ins| data = insert_to(data, ins) }
@data = data
end
Expand Down
11 changes: 6 additions & 5 deletions lib/rdf/util.rb
@@ -1,7 +1,8 @@
module RDF; module Util
autoload :Aliasing, 'rdf/util/aliasing'
autoload :Cache, 'rdf/util/cache'
autoload :File, 'rdf/util/file'
autoload :Logger, 'rdf/util/logger'
autoload :UUID, 'rdf/util/uuid'
autoload :Aliasing, 'rdf/util/aliasing'
autoload :Cache, 'rdf/util/cache'
autoload :File, 'rdf/util/file'
autoload :Logger, 'rdf/util/logger'
autoload :UUID, 'rdf/util/uuid'
autoload :Coercions, 'rdf/util/coercions'
end; end
60 changes: 60 additions & 0 deletions lib/rdf/util/coercions.rb
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
module RDF
module Util
module Coercions
# This is a provisional module intended to house input
# coercions. Currently the only coercion is a statement
# preprocessor that is used in e.g. {RDF::Writable#insert} and
# {RDF::Mutable#delete}.

protected

##
# Coerce an array of arguments into {RDF::Statement}, or
# {RDF::Enumerable} and then yield to a block. Note that this
# code was amalgamated from that which was sandwiched around
# both {RDF::Writable#insert_statements} and
# {RDF::Mutable#delete_statements}. The parameters `query` and
# `constant` are therefore present to handle the conditions
# where the statements contain wildcards and what to do about
# them.
#
# @example
# coerce_statements(statements) { |value| do_something(value) }
#
# @param statements [#map] The arbitrary-ish input to be manipulated
# @param query [false, true] Whether to call `query` before the block
# (as expected by {Mutable#delete_statements})
# @param constant [false, true] Whether to test if the statements
# are constant (as expected by {Mutable#delete_statements})
# @yield [RDF::Statement, RDF::Enumerable]
# @return statements
def coerce_statements(statements, query: false, constant: false, &block)
raise ArgumentError, 'expecting a block' unless block_given?

statements = statements.map do |value|
case
when value.respond_to?(:each_statement)
block.call(value)
nil
when (statement = Statement.from(value)) &&
(!constant || statement.constant?)
statement
when query
# XXX note that this only makes sense when the module is include()d
block.call(self.query(value))
nil
else
raise ArgumentError, "Not a valid statement: #{value.inspect}"
end
end.compact

block.call(statements) unless statements.empty?

# eh might as well return these
statements
end

end
end
end
2 changes: 1 addition & 1 deletion lib/rdf/vocab/xsd.rb
Expand Up @@ -190,7 +190,7 @@ class XSD < RDF::Vocabulary("http://www.w3.org/2001/XMLSchema#")
comment: %(
boolean represents the values of two-valued logic.
).freeze,
label: "base64Binary".freeze,
label: "boolean".freeze,
subClassOf: "xsd:anyAtomicType".freeze,
type: "rdfs:Datatype".freeze
term :byte,
Expand Down
4 changes: 2 additions & 2 deletions rdf.gemspec
Expand Up @@ -33,8 +33,8 @@ Gem::Specification.new do |gem|
gem.add_runtime_dependency 'hamster', '~> 3.0'
gem.add_development_dependency 'rdf-spec', '~> 3.1'
gem.add_development_dependency 'rdf-turtle', '~> 3.1'
gem.add_development_dependency 'rdf-vocab', '~> 3.0'
gem.add_development_dependency 'rdf-xsd', '~> 3.0'
gem.add_development_dependency 'rdf-vocab', '~> 3.1'
gem.add_development_dependency 'rdf-xsd', '~> 3.1'
gem.add_development_dependency 'rest-client', '~> 2.1'
gem.add_development_dependency 'rspec', '~> 3.9'
gem.add_development_dependency 'rspec-its', '~> 1.3'
Expand Down
11 changes: 10 additions & 1 deletion spec/changeset_spec.rb
Expand Up @@ -28,7 +28,7 @@
its(:deletes) { is_expected.to be_a(RDF::Enumerable) }
its(:inserts) { is_expected.to be_a(RDF::Enumerable) }

it { is_expected.to be_mutable }
it { is_expected.to_not be_mutable }
it { is_expected.to_not be_readable }

it "does not respond to #load" do
Expand Down Expand Up @@ -73,6 +73,14 @@
expect { subject.apply(repo) }
.to change { repo.statements }.to contain_exactly(new_statement)
end

it "correctly applies a wildcard/pattern" do
repo << st

subject.delete RDF::Statement(nil, RDF::URI('p'), nil)

expect { subject.apply(repo) }.to change { repo.statements }.to be_empty
end
end
end

Expand Down Expand Up @@ -127,4 +135,5 @@
.to change { subject.inserts }.to contain_exactly(*statements)
end
end

end

0 comments on commit a24805a

Please sign in to comment.