changesets 0.1
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/README.md +32 -0
- data/Rakefile +60 -0
- data/lib/changesets.rb +4 -0
- data/lib/changesets/rdf_changeset.rb +139 -0
- data/tests/tc_rdf_changeset.rb +158 -0
- data/tests/ts_changeset.rb +2 -0
- metadata +102 -0
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
CHANGESET.RB
|
2
|
+
------------
|
3
|
+
|
4
|
+
A plugin for RDF.rb that provides support for creating Changesets that describe changes to an RDF
|
5
|
+
graph[1].
|
6
|
+
|
7
|
+
Changesets can be serialized as RDF and then applied to a triple store. Changesets are currently supported
|
8
|
+
by Talis Platform stores and Kasabi[0] datasets.
|
9
|
+
|
10
|
+
AUTHOR
|
11
|
+
------
|
12
|
+
|
13
|
+
Leigh Dodds (ld@kasabi.com)
|
14
|
+
|
15
|
+
INSTALLATION
|
16
|
+
------------
|
17
|
+
|
18
|
+
Changesets.rb is packaged as a Ruby Gem and can be installed as follows:
|
19
|
+
|
20
|
+
sudo gem install changesets
|
21
|
+
|
22
|
+
The source for the project is maintained in github at:
|
23
|
+
|
24
|
+
http://github.com/ldodds/changesets.rb
|
25
|
+
|
26
|
+
USAGE
|
27
|
+
-----
|
28
|
+
|
29
|
+
The test suite provides some simple examples of how to construct changesets.
|
30
|
+
|
31
|
+
[0]: [http://kasabi.com]
|
32
|
+
[1]: [http://vocab.org/changeset/schema.html]
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/clean'
|
7
|
+
|
8
|
+
NAME = "changesets"
|
9
|
+
VER = "0.1"
|
10
|
+
|
11
|
+
RDOC_OPTS = ['--quiet', '--title', 'RDF Changesets API']
|
12
|
+
|
13
|
+
PKG_FILES = %w( README.md Rakefile ) +
|
14
|
+
Dir.glob("{tests,lib}/**/*")
|
15
|
+
|
16
|
+
CLEAN.include ['*.gem', 'pkg']
|
17
|
+
SPEC =
|
18
|
+
Gem::Specification.new do |s|
|
19
|
+
s.name = NAME
|
20
|
+
s.version = VER
|
21
|
+
s.platform = Gem::Platform::RUBY
|
22
|
+
s.required_ruby_version = ">= 1.8.7"
|
23
|
+
s.has_rdoc = true
|
24
|
+
s.rdoc_options = RDOC_OPTS
|
25
|
+
s.summary = "RDF Changesets API"
|
26
|
+
s.description = s.summary
|
27
|
+
s.author = "Leigh Dodds"
|
28
|
+
s.email = 'ld@kasabi.com'
|
29
|
+
s.homepage = 'http://github.com/ldodds/changesets.rb'
|
30
|
+
s.files = PKG_FILES
|
31
|
+
s.require_path = "lib"
|
32
|
+
s.test_file = "tests/ts_changeset.rb"
|
33
|
+
s.add_dependency("rdf")
|
34
|
+
s.add_dependency("mocha", ">= 0.9.5")
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::GemPackageTask.new(SPEC) do |pkg|
|
38
|
+
pkg.need_tar = true
|
39
|
+
end
|
40
|
+
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
43
|
+
rdoc.options += RDOC_OPTS
|
44
|
+
rdoc.rdoc_files.include("CHANGES", "lib/**/*.rb")
|
45
|
+
end
|
46
|
+
|
47
|
+
Rake::TestTask.new do |test|
|
48
|
+
test.test_files = FileList['tests/tc_*.rb']
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Install from a locally built copy of the gem"
|
52
|
+
task :install do
|
53
|
+
sh %{rake package}
|
54
|
+
sh %{sudo gem install pkg/#{NAME}-#{VER}}
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Uninstall the gem"
|
58
|
+
task :uninstall => [:clean] do
|
59
|
+
sh %{sudo gem uninstall #{NAME}}
|
60
|
+
end
|
data/lib/changesets.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
module RDF
|
2
|
+
module Talis
|
3
|
+
class Changeset < RDF::Vocabulary('http://purl.org/vocab/changeset/schema#')
|
4
|
+
property :removal
|
5
|
+
property :addition
|
6
|
+
property :creatorName
|
7
|
+
property :createdDate
|
8
|
+
property :subjectOfChange
|
9
|
+
property :changeReason
|
10
|
+
property :ChangeSet
|
11
|
+
property :precedingChangeSet
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module RDF
|
17
|
+
|
18
|
+
class Changeset
|
19
|
+
|
20
|
+
#Media type for Changesets
|
21
|
+
CONTENT_TYPE_TURTLE = "application/vnd.talis.changeset+turtle"
|
22
|
+
CONTENT_TYPE_XML = "application/vnd.talis.changeset+xml"
|
23
|
+
#Default reason for applying the update to a graph
|
24
|
+
DEFAULT_REASON = "Generated in changeset.rb"
|
25
|
+
#Default name/label for the change agent
|
26
|
+
DEFAULT_CREATOR = "changeset.rb"
|
27
|
+
|
28
|
+
attr_reader :statements, :subject_of_change
|
29
|
+
|
30
|
+
def initialize(subject_of_change, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
31
|
+
@resource = RDF::Node.new
|
32
|
+
@subject_of_change = subject_of_change
|
33
|
+
@statements = []
|
34
|
+
@statements.concat [RDF::Statement.new(@resource, RDF.type, RDF::Talis::Changeset.ChangeSet),
|
35
|
+
RDF::Statement.new(@resource, RDF::Talis::Changeset.changeReason, change_reason),
|
36
|
+
RDF::Statement.new(@resource, RDF::Talis::Changeset.creatorName, creator_name),
|
37
|
+
RDF::Statement.new(@resource, RDF::Talis::Changeset.createdDate, Time.now),
|
38
|
+
RDF::Statement.new(@resource, RDF::Talis::Changeset.subjectOfChange, subject_of_change)]
|
39
|
+
if block_given?
|
40
|
+
yield self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#Remove these statements from the graph
|
45
|
+
def remove_statements(stmts)
|
46
|
+
stmts = [stmts] if stmts.is_a?(RDF::Statement)
|
47
|
+
stmts.each do |stmt|
|
48
|
+
raise ArgumentError unless stmt.subject == @subject_of_change
|
49
|
+
@statements.concat changeset_statement(stmt, :removal)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#Add these statements to the graph
|
54
|
+
def add_statements(stmts)
|
55
|
+
stmts = [stmts] if stmts.is_a?(RDF::Statement)
|
56
|
+
stmts.each do |stmt|
|
57
|
+
next unless stmt
|
58
|
+
raise ArgumentError unless stmt.subject == @subject_of_change
|
59
|
+
@statements.concat changeset_statement(stmt, :addition)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def changeset_statement(stmt, action)
|
64
|
+
s = RDF::Node.new
|
65
|
+
[RDF::Statement.new(@resource, RDF::Talis::Changeset.send(action), s),
|
66
|
+
RDF::Statement.new(s, RDF.type, RDF.to_rdf+"Statement"),
|
67
|
+
RDF::Statement.new(s, RDF.subject, stmt.subject),
|
68
|
+
RDF::Statement.new(s, RDF.predicate, stmt.predicate),
|
69
|
+
RDF::Statement.new(s, RDF.object, stmt.object)]
|
70
|
+
end
|
71
|
+
|
72
|
+
#Convert into an RDF::Graph object
|
73
|
+
def to_graph
|
74
|
+
graph = RDF::Graph.new()
|
75
|
+
@statements.each do |s|
|
76
|
+
graph << s
|
77
|
+
end
|
78
|
+
graph
|
79
|
+
end
|
80
|
+
|
81
|
+
#Update a predicate from one value to another
|
82
|
+
#Will only remove the specified old value, other values for predicate will remain unchanged
|
83
|
+
def Changeset.update_property(subject, predicate, old_value, new_value, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
84
|
+
cs = Changeset.new(subject, change_reason, creator_name) do |cs|
|
85
|
+
cs.remove_statements( RDF::Statement.new( subject, predicate, old_value ) )
|
86
|
+
cs.add_statements( RDF::Statement.new( subject, predicate, new_value ) )
|
87
|
+
end
|
88
|
+
cs
|
89
|
+
end
|
90
|
+
|
91
|
+
#Remove a specific single property for a subject
|
92
|
+
def Changeset.remove_property(subject, predicate, value, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
93
|
+
return Changeset.remove_statement( RDF::Statement.new( subject, predicate, value ) )
|
94
|
+
end
|
95
|
+
|
96
|
+
#Remove a statement
|
97
|
+
def Changeset.remove_statement( statement, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
98
|
+
cs = Changeset.new(statement.subject, change_reason, creator_name) do |cs|
|
99
|
+
cs.remove_statements( statement )
|
100
|
+
end
|
101
|
+
cs
|
102
|
+
end
|
103
|
+
|
104
|
+
#Remove all statements with a specific predicate for a specific resource
|
105
|
+
def Changeset.remove_properties(subject, predicate, graph, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
106
|
+
cs = Changeset.new(subject, change_reason, creator_name) do |cs|
|
107
|
+
graph.query( [subject, predicate, nil] ).each do |statement|
|
108
|
+
cs.remove_statements( statement )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
cs
|
112
|
+
end
|
113
|
+
|
114
|
+
#Remove all statements where the indicated resource is the subject
|
115
|
+
def Changeset.remove_subject(subject, graph, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
116
|
+
cs = Changeset.new(subject, change_reason, creator_name) do |cs|
|
117
|
+
graph.query( [subject, nil, nil] ).each do |statement|
|
118
|
+
cs.remove_statements( statement )
|
119
|
+
end
|
120
|
+
end
|
121
|
+
cs
|
122
|
+
end
|
123
|
+
|
124
|
+
#Apply an update by removing all statements for the indicated subject from the old graph, replacing it
|
125
|
+
#with statements in the new graph
|
126
|
+
def Changeset.update(subject, new, old, change_reason=DEFAULT_REASON, creator_name=DEFAULT_CREATOR)
|
127
|
+
cs = Changeset.new(subject, change_reason, creator_name) do |cs|
|
128
|
+
old.query( [subject, nil, nil] ).each do |statement|
|
129
|
+
cs.remove_statements( statement )
|
130
|
+
end
|
131
|
+
new.query( [subject, nil, nil] ).each do |statement|
|
132
|
+
cs.add_statements( statement )
|
133
|
+
end
|
134
|
+
end
|
135
|
+
cs
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
require 'changesets'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class ChangesetTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_init
|
9
|
+
cs = RDF::Changeset.new( RDF::URI.new("http://www.example.org") )
|
10
|
+
assert_equal( RDF::URI.new("http://www.example.org"), cs.subject_of_change )
|
11
|
+
assert_equal( false, cs.statements.empty? )
|
12
|
+
|
13
|
+
graph = cs.to_graph()
|
14
|
+
assert_not_nil( graph )
|
15
|
+
assert_equal( cs.statements.length, cs.to_graph.size )
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_add_single_statement
|
19
|
+
uri = RDF::URI.new("http://www.example.org")
|
20
|
+
cs = RDF::Changeset.new( uri )
|
21
|
+
stmts = RDF::Statement.new( uri , RDF.type, RDF::RDFS.Class )
|
22
|
+
cs.add_statements( stmts )
|
23
|
+
test_for( RDF::Talis::Changeset.addition, cs, stmts )
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_remove_single_statement
|
27
|
+
uri = RDF::URI.new("http://www.example.org")
|
28
|
+
cs = RDF::Changeset.new( uri )
|
29
|
+
stmts = RDF::Statement.new( uri , RDF.type, RDF::RDFS.Class )
|
30
|
+
cs.remove_statements( stmts )
|
31
|
+
test_for( RDF::Talis::Changeset.removal, cs, stmts )
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_add_statements
|
35
|
+
uri = RDF::URI.new("http://www.example.org")
|
36
|
+
cs = RDF::Changeset.new( uri )
|
37
|
+
stmts = [ RDF::Statement.new( uri , RDF.type, RDF::RDFS.Class ) ]
|
38
|
+
cs.add_statements( stmts )
|
39
|
+
test_for( RDF::Talis::Changeset.addition, cs, stmts )
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_remove_statements
|
43
|
+
uri = RDF::URI.new("http://www.example.org")
|
44
|
+
cs = RDF::Changeset.new( uri )
|
45
|
+
stmts = [ RDF::Statement.new( uri , RDF.type, RDF::RDFS.Class ) ]
|
46
|
+
cs.remove_statements( stmts )
|
47
|
+
test_for( RDF::Talis::Changeset.removal, cs, stmts )
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_precondition
|
51
|
+
uri = RDF::URI.new("http://www.example.org")
|
52
|
+
other = RDF::URI.new("http://www.example.com")
|
53
|
+
cs = RDF::Changeset.new( uri )
|
54
|
+
|
55
|
+
assert_raise ArgumentError do
|
56
|
+
cs.add_statements( RDF::Statement.new( other , RDF.type, RDF::RDFS.Class ) )
|
57
|
+
end
|
58
|
+
assert_raise ArgumentError do
|
59
|
+
cs.remove_statements( RDF::Statement.new( other , RDF.type, RDF::RDFS.Class ) )
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_update_property()
|
65
|
+
uri = RDF::URI.new("http://www.example.org")
|
66
|
+
cs = RDF::Changeset.update_property(uri, RDF::RDFS.label, RDF::Literal.new("Old"), RDF::Literal.new("New") )
|
67
|
+
removal = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Old"))
|
68
|
+
addition = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("New"))
|
69
|
+
test_for( RDF::Talis::Changeset.removal, cs, removal )
|
70
|
+
test_for( RDF::Talis::Changeset.addition, cs, addition )
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_remove_property()
|
74
|
+
uri = RDF::URI.new("http://www.example.org")
|
75
|
+
cs = RDF::Changeset.remove_property(uri, RDF::RDFS.label, RDF::Literal.new("Gone") )
|
76
|
+
removal = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Gone"))
|
77
|
+
test_for( RDF::Talis::Changeset.removal, cs, removal )
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_remove_statement()
|
81
|
+
uri = RDF::URI.new("http://www.example.org")
|
82
|
+
removal = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Gone") )
|
83
|
+
cs = RDF::Changeset.remove_statement( removal )
|
84
|
+
test_for( RDF::Talis::Changeset.removal, cs, removal )
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_remove_properties()
|
88
|
+
uri = RDF::URI.new("http://www.example.org")
|
89
|
+
graph = RDF::Graph.new()
|
90
|
+
label = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Label") )
|
91
|
+
title = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Title") )
|
92
|
+
graph << label
|
93
|
+
graph << title
|
94
|
+
cs = RDF::Changeset.remove_properties(uri, RDF::RDFS.label, graph )
|
95
|
+
#puts cs.statements
|
96
|
+
test_for( RDF::Talis::Changeset.removal, cs, label )
|
97
|
+
test_for( RDF::Talis::Changeset.removal, cs, title )
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_remove_subject()
|
101
|
+
uri = RDF::URI.new("http://www.example.org")
|
102
|
+
graph = RDF::Graph.new()
|
103
|
+
label = RDF::Statement.new( uri, RDF::RDFS.label, "Label")
|
104
|
+
title = RDF::Statement.new( uri, RDF::DC.title, "Title")
|
105
|
+
graph << label
|
106
|
+
graph << title
|
107
|
+
cs = RDF::Changeset.remove_subject(uri, graph )
|
108
|
+
test_for( RDF::Talis::Changeset.removal, cs, [ label, title ] )
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_update()
|
112
|
+
uri = RDF::URI.new("http://www.example.org")
|
113
|
+
graph = RDF::Graph.new()
|
114
|
+
label = RDF::Statement.new( uri, RDF::RDFS.label, "Label")
|
115
|
+
title = RDF::Statement.new( uri, RDF::DC.title, "Title")
|
116
|
+
graph << label
|
117
|
+
graph << title
|
118
|
+
cs = RDF::Changeset.update(uri, RDF::Graph.new(), graph )
|
119
|
+
test_for( RDF::Talis::Changeset.removal, cs, [ label, title ] )
|
120
|
+
|
121
|
+
cs = RDF::Changeset.update(uri, graph, RDF::Graph.new() )
|
122
|
+
test_for( RDF::Talis::Changeset.addition, cs, [ label, title ] )
|
123
|
+
end
|
124
|
+
|
125
|
+
# def test_apply_to()
|
126
|
+
# uri = RDF::URI.new("http://www.example.org")
|
127
|
+
# graph = RDF::Graph.new()
|
128
|
+
# label = RDF::Statement.new( uri, RDF::RDFS.label, RDF::Literal.new("Label") )
|
129
|
+
# title = RDF::Statement.new( uri, RDF::DC.title, RDF::Literal.new("Title") )
|
130
|
+
# graph << label
|
131
|
+
# graph << title
|
132
|
+
# cs = RDF::Changeset.remove_properties(uri, RDF::RDFS.label, graph )
|
133
|
+
#
|
134
|
+
# cs.apply_to(graph)
|
135
|
+
#
|
136
|
+
# label = graph.first_object( [uri, RDF::RDFS.label, nil ] )
|
137
|
+
# assert_nil(label)
|
138
|
+
# end
|
139
|
+
|
140
|
+
|
141
|
+
def test_for( predicate, cs, statements )
|
142
|
+
statements = [statements] if statements.is_a?(RDF::Statement)
|
143
|
+
|
144
|
+
statements.each do |s|
|
145
|
+
query = RDF::Query.new do
|
146
|
+
pattern [ :x, predicate, :stmt ]
|
147
|
+
pattern [ :stmt, RDF.subject, s.subject]
|
148
|
+
pattern [ :stmt, RDF.predicate, s.predicate]
|
149
|
+
pattern [ :stmt, RDF.object, s.object]
|
150
|
+
end
|
151
|
+
query.execute(cs.to_graph)
|
152
|
+
if query.failed?
|
153
|
+
raise "Unable to find #{predicate} for #{s.subject} #{s.predicate}, #{s.object}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: changesets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: "0.1"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Leigh Dodds
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-10-12 00:00:00 Z
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: rdf
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: mocha
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 49
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
- 9
|
45
|
+
- 5
|
46
|
+
version: 0.9.5
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
description: RDF Changesets API
|
50
|
+
email: ld@kasabi.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- tests/ts_changeset.rb
|
61
|
+
- tests/tc_rdf_changeset.rb
|
62
|
+
- lib/changesets.rb
|
63
|
+
- lib/changesets/rdf_changeset.rb
|
64
|
+
homepage: http://github.com/ldodds/changesets.rb
|
65
|
+
licenses: []
|
66
|
+
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --quiet
|
70
|
+
- --title
|
71
|
+
- RDF Changesets API
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 57
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 8
|
83
|
+
- 7
|
84
|
+
version: 1.8.7
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.8.9
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: RDF Changesets API
|
101
|
+
test_files:
|
102
|
+
- tests/ts_changeset.rb
|