active-triples 0.10.2 → 0.11.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.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGES.md +17 -11
- data/README.md +72 -39
- data/lib/active_triples/configurable.rb +6 -1
- data/lib/active_triples/list.rb +1 -4
- data/lib/active_triples/nested_attributes.rb +10 -7
- data/lib/active_triples/persistable.rb +13 -0
- data/lib/active_triples/persistence_strategies/parent_strategy.rb +47 -34
- data/lib/active_triples/persistence_strategies/persistence_strategy.rb +14 -1
- data/lib/active_triples/properties.rb +19 -4
- data/lib/active_triples/property_builder.rb +4 -4
- data/lib/active_triples/rdf_source.rb +142 -189
- data/lib/active_triples/relation.rb +307 -156
- data/lib/active_triples/util/buffered_transaction.rb +126 -0
- data/lib/active_triples/util/extended_bounded_description.rb +75 -0
- data/lib/active_triples/version.rb +1 -1
- data/spec/active_triples/configurable_spec.rb +35 -7
- data/spec/active_triples/identifiable_spec.rb +19 -6
- data/spec/active_triples/list_spec.rb +15 -7
- data/spec/active_triples/nested_attributes_spec.rb +12 -10
- data/spec/active_triples/persistable_spec.rb +0 -4
- data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +57 -10
- data/spec/active_triples/rdf_source_spec.rb +137 -97
- data/spec/active_triples/relation_spec.rb +436 -132
- data/spec/active_triples/resource_spec.rb +8 -23
- data/spec/active_triples/util/buffered_transaction_spec.rb +187 -0
- data/spec/active_triples/util/extended_bounded_description_spec.rb +98 -0
- data/spec/integration/reciprocal_properties_spec.rb +10 -10
- data/spec/support/matchers.rb +13 -1
- metadata +7 -3
@@ -94,7 +94,7 @@ describe ActiveTriples::Resource do
|
|
94
94
|
|
95
95
|
it 'should not be settable' do
|
96
96
|
expect{ subject.set_subject! RDF::URI('http://example.org/moomin2') }
|
97
|
-
.to raise_error 'Refusing update URI when one is already assigned!'
|
97
|
+
.to raise_error 'Refusing to update URI when one is already assigned!'
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
@@ -342,22 +342,14 @@ describe ActiveTriples::Resource do
|
|
342
342
|
end
|
343
343
|
|
344
344
|
context 'with a parent' do
|
345
|
-
|
345
|
+
let(:parent) { DummyResource.new('http://example.org/mummi') }
|
346
346
|
|
347
|
-
|
348
|
-
DummyResource.new('http://example.org/moomi')
|
349
|
-
end
|
347
|
+
before { parent.license = subject }
|
350
348
|
|
351
349
|
it 'empties the graph and removes it from the parent' do
|
352
350
|
expect { parent.license.first.destroy! }
|
353
351
|
.to change { parent.license.empty? }.to true
|
354
352
|
end
|
355
|
-
|
356
|
-
it 'removes its whole graph from the parent' do
|
357
|
-
statements = subject.statements.to_a
|
358
|
-
parent.license.first.destroy
|
359
|
-
statements.each { |s| expect(parent.statements).not_to include s }
|
360
|
-
end
|
361
353
|
end
|
362
354
|
end
|
363
355
|
|
@@ -579,21 +571,14 @@ describe ActiveTriples::Resource do
|
|
579
571
|
context "literals are set" do
|
580
572
|
let(:literal1) { RDF::Literal.new("test", :language => :en) }
|
581
573
|
let(:literal2) { RDF::Literal.new("test", :language => :fr) }
|
574
|
+
|
582
575
|
before do
|
583
576
|
subject.set_value(RDF::Vocab::DC.title, [literal1, literal2])
|
584
577
|
end
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
.to contain_exactly "test", "test"
|
590
|
-
end
|
591
|
-
end
|
592
|
-
context "and literals are requested" do
|
593
|
-
it "should return literals" do
|
594
|
-
expect(subject.get_values(RDF::Vocab::DC.title, :literal => true))
|
595
|
-
.to contain_exactly literal1, literal2
|
596
|
-
end
|
578
|
+
|
579
|
+
it "should return literals" do
|
580
|
+
expect(subject.get_values(RDF::Vocab::DC.title, :literal => true))
|
581
|
+
.to contain_exactly literal1, literal2
|
597
582
|
end
|
598
583
|
end
|
599
584
|
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require 'rdf/spec/transaction'
|
4
|
+
require 'active_triples/util/buffered_transaction'
|
5
|
+
|
6
|
+
describe ActiveTriples::BufferedTransaction do
|
7
|
+
subject { described_class.new(repository, mutable: true) }
|
8
|
+
|
9
|
+
let(:repository) { RDF::Repository.new }
|
10
|
+
|
11
|
+
shared_context 'with a subject' do
|
12
|
+
subject do
|
13
|
+
described_class
|
14
|
+
.new(repository, mutable: true, subject: term, ancestors: [ancestor])
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:term) { RDF::URI('http://example.com/mummi') }
|
18
|
+
let(:ancestor) { RDF::URI('http://example.com/moomin_papa') }
|
19
|
+
|
20
|
+
let(:included_statements) do
|
21
|
+
[RDF::Statement(term, RDF::URI('p1'), 'o'),
|
22
|
+
RDF::Statement(term, RDF::URI('p2'), 0),
|
23
|
+
RDF::Statement(term, RDF::URI('p3'), :o),
|
24
|
+
RDF::Statement(:o, RDF::URI('p4'), ancestor)]
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:excluded_statements) do
|
28
|
+
[RDF::Statement(RDF::URI('s1'), RDF::URI('p1'), 'o'),
|
29
|
+
RDF::Statement(:s2, RDF::URI('p2'), 0),
|
30
|
+
RDF::Statement(:s3, RDF::URI('p3'), :o),
|
31
|
+
RDF::Statement(ancestor, RDF::URI('p4'), :o)]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples 'a buffered changeset' do
|
36
|
+
let(:st) { RDF::Statement(:s, RDF::URI('p'), 'o') }
|
37
|
+
|
38
|
+
it 'adds inserts' do
|
39
|
+
expect { subject.insert(st) }
|
40
|
+
.to change { subject.changes.inserts }.to contain_exactly(st)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'removes deletes when inserting' do
|
44
|
+
subject.delete(st)
|
45
|
+
|
46
|
+
expect { subject.insert(st) }
|
47
|
+
.to change { subject.changes.deletes }.to be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'adds deletes' do
|
51
|
+
expect { subject.delete(st) }
|
52
|
+
.to change { subject.changes.deletes }.to contain_exactly(st)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'removes inserts when deleting' do
|
56
|
+
subject.insert(st)
|
57
|
+
|
58
|
+
expect { subject.delete(st) }
|
59
|
+
.to change { subject.changes.inserts }.to be_empty
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
shared_examples 'an optimist' do; end
|
64
|
+
|
65
|
+
# @see lib/rdf/spec/transaction.rb in rdf-spec
|
66
|
+
it_behaves_like 'an RDF::Transaction', ActiveTriples::BufferedTransaction
|
67
|
+
|
68
|
+
it_behaves_like 'a buffered changeset'
|
69
|
+
it_behaves_like 'an optimist'
|
70
|
+
|
71
|
+
it 'supports snapshots' do
|
72
|
+
expect(subject.supports?(:snapshots)).to be true
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'is :repeatable_read' do
|
76
|
+
expect(subject.isolation_level).to eq :repeatable_read
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#snapshot' do
|
80
|
+
it 'returns its current internal state'
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#each' do
|
84
|
+
context 'when projecting' do
|
85
|
+
include_context 'with a subject'
|
86
|
+
|
87
|
+
before do
|
88
|
+
subject.insert(*included_statements)
|
89
|
+
subject.insert(*excluded_statements)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'projects over a bounded description' do
|
93
|
+
expect(subject).to contain_exactly(*included_statements)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#data' do
|
99
|
+
it 'returns itself' do
|
100
|
+
expect(subject.data).to eq subject
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# This API changed. Need to rework these tests for the RDFSource as Repository case
|
105
|
+
# context 'with trasaction as repository' do
|
106
|
+
# subject { described_class.new(repository, mutable: true) }
|
107
|
+
# let(:repository) { described_class.new(RDF::Repository.new, mutable: true) }
|
108
|
+
|
109
|
+
# it_behaves_like 'a buffered changeset'
|
110
|
+
# it_behaves_like 'an optimist'
|
111
|
+
|
112
|
+
# describe '#execute' do
|
113
|
+
# it 'does not reflect changes to parent' do
|
114
|
+
# st = [:s, RDF::URI(:p), 'o']
|
115
|
+
# expect { repository.insert(st) }.not_to change { subject.statements }
|
116
|
+
# end
|
117
|
+
|
118
|
+
# it 'does not executed changes to parent' do
|
119
|
+
# st = [:s, RDF::URI(:p), 'o']
|
120
|
+
# expect { repository.insert(st); repository.execute }
|
121
|
+
# .not_to change { subject.statements }
|
122
|
+
# end
|
123
|
+
|
124
|
+
# context 'with no changes' do
|
125
|
+
# it 'leaves parent tx unchanged' do
|
126
|
+
# expect { subject.execute }.not_to change { repository.statements }
|
127
|
+
# end
|
128
|
+
|
129
|
+
# it 'leaves parent tx insert buffer unchanged' do
|
130
|
+
# expect { subject.execute }.not_to change { repository.changes.inserts }
|
131
|
+
# end
|
132
|
+
|
133
|
+
# it 'leaves parent tx delete buffer unchanged' do
|
134
|
+
# expect { subject.execute }.not_to change { repository.changes.deletes }
|
135
|
+
# end
|
136
|
+
|
137
|
+
# it 'leaves top level repository unchanged' do
|
138
|
+
# expect { subject.execute }
|
139
|
+
# .not_to change { repository.repository.statements }
|
140
|
+
# end
|
141
|
+
# end
|
142
|
+
|
143
|
+
# context 'with changes' do
|
144
|
+
# let(:ins) { RDF::Statement(:ins, RDF::URI('p'), 'o') }
|
145
|
+
# let(:del) { RDF::Statement(:del, RDF::URI('p'), 'o') }
|
146
|
+
|
147
|
+
# before do
|
148
|
+
# subject.insert(ins)
|
149
|
+
# subject.delete(del)
|
150
|
+
# end
|
151
|
+
|
152
|
+
# it 'adds to parent tx insert buffer' do
|
153
|
+
# expect { subject.execute }
|
154
|
+
# .to change { repository.changes.inserts }.to contain_exactly(ins)
|
155
|
+
# end
|
156
|
+
|
157
|
+
# it 'adds to parent tx delete buffer' do
|
158
|
+
# expect { subject.execute }
|
159
|
+
# .to change { repository.changes.deletes }.to contain_exactly(del)
|
160
|
+
# end
|
161
|
+
|
162
|
+
# it 'mutates parent statements' do
|
163
|
+
# repository.insert(del)
|
164
|
+
|
165
|
+
# expect { subject.execute }
|
166
|
+
# .to change { repository.statements }
|
167
|
+
# .from(contain_exactly(del))
|
168
|
+
# .to contain_exactly(ins)
|
169
|
+
# end
|
170
|
+
|
171
|
+
# context 'and parent is committed' do
|
172
|
+
# before do
|
173
|
+
# repository.insert(del)
|
174
|
+
# repository.execute
|
175
|
+
# end
|
176
|
+
|
177
|
+
# it 'mutates parent statements' do
|
178
|
+
# expect { subject.execute }
|
179
|
+
# .to change { repository.statements }
|
180
|
+
# .from(contain_exactly(del))
|
181
|
+
# .to contain_exactly(ins)
|
182
|
+
# end
|
183
|
+
# end
|
184
|
+
# end
|
185
|
+
# end
|
186
|
+
# end
|
187
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require 'rdf/spec/enumerable'
|
4
|
+
require 'rdf/spec/queryable'
|
5
|
+
require 'active_triples/util/extended_bounded_description'
|
6
|
+
|
7
|
+
describe ActiveTriples::ExtendedBoundedDescription do
|
8
|
+
subject { described_class.new(source_graph, starting_node, ancestors) }
|
9
|
+
|
10
|
+
let(:ancestors) { [] }
|
11
|
+
let(:source_graph) { RDF::Repository.new }
|
12
|
+
let(:starting_node) { RDF::Node.new }
|
13
|
+
|
14
|
+
it { is_expected.not_to be_mutable }
|
15
|
+
|
16
|
+
shared_examples 'a bounded description' do
|
17
|
+
before do
|
18
|
+
source_graph.insert(*included_statements)
|
19
|
+
source_graph.insert(*excluded_statements)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'projects over a bounded description' do
|
23
|
+
expect(subject).to contain_exactly(*included_statements)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'can iterate repeatedly' do
|
27
|
+
expect(subject).to contain_exactly(*included_statements)
|
28
|
+
expect(subject).to contain_exactly(*included_statements)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'is queryable' do
|
32
|
+
expect(subject.query([nil, nil, nil]))
|
33
|
+
.to contain_exactly(*included_statements)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# *** We don't pass these RDF::Spec examples.
|
39
|
+
# They try to test boring things, like having the triples we put in.
|
40
|
+
#
|
41
|
+
# @see lib/rdf/spec/enumerable.rb in rdf-spec
|
42
|
+
# it_behaves_like 'an RDF::Enumerable' do
|
43
|
+
# let(:graph) { RDF::Repository.new.insert(*statements) }
|
44
|
+
# let(:statements) { RDF::Spec.quads }
|
45
|
+
#
|
46
|
+
# let(:enumerable) do
|
47
|
+
# ActiveTriples::ExtendedBoundedDescription
|
48
|
+
# .new(graph, statements.first.subject)
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# @see lib/rdf/spec/queryable.rb in rdf-spec
|
53
|
+
# it_behaves_like 'an RDF::Queryable' do
|
54
|
+
# let(:graph) { RDF::Repository.new.insert(*statements) }
|
55
|
+
# let(:statements) { RDF::Spec.quads }
|
56
|
+
#
|
57
|
+
# let(:queryable) do
|
58
|
+
# ActiveTriples::ExtendedBoundedDescription
|
59
|
+
# .new(graph, statements.first.subject)
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# *** end boring stuff
|
64
|
+
##
|
65
|
+
|
66
|
+
let(:included_statements) do
|
67
|
+
[RDF::Statement(starting_node, RDF::URI('p1'), 'o'),
|
68
|
+
RDF::Statement(starting_node, RDF::URI('p2'), 0),
|
69
|
+
RDF::Statement(starting_node, RDF::URI('p3'), :o1),
|
70
|
+
RDF::Statement(:o1, RDF::URI('p4'), :o2),
|
71
|
+
RDF::Statement(:o1, RDF::URI('p5'), 'w0w'),
|
72
|
+
RDF::Statement(:o2, RDF::URI('p6'), :o1)]
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:excluded_statements) do
|
76
|
+
[RDF::Statement(RDF::URI('s1'), RDF::URI('p1'), 'o'),
|
77
|
+
RDF::Statement(:s2, RDF::URI('p2'), 0),
|
78
|
+
RDF::Statement(:s3, RDF::URI('p3'), :o),
|
79
|
+
RDF::Statement(:s3, RDF::URI('p3'), starting_node)]
|
80
|
+
end
|
81
|
+
|
82
|
+
it_behaves_like 'a bounded description'
|
83
|
+
|
84
|
+
context 'with ancestors' do
|
85
|
+
before do
|
86
|
+
included_statements <<
|
87
|
+
RDF::Statement(starting_node, RDF::URI('a'), ancestor)
|
88
|
+
|
89
|
+
excluded_statements <<
|
90
|
+
RDF::Statement(ancestor, RDF::URI('a'), starting_node)
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:ancestor) { RDF::Node.new(:ancestor) }
|
94
|
+
let(:ancestors) { [ancestor] }
|
95
|
+
|
96
|
+
it_behaves_like 'a bounded description'
|
97
|
+
end
|
98
|
+
end
|
@@ -28,13 +28,13 @@ describe 'reciprocal properties' do
|
|
28
28
|
|
29
29
|
a.has_resource = b
|
30
30
|
expect(a.has_resource).to eq [b]
|
31
|
-
expect(a.label).to
|
32
|
-
expect(b.label).to
|
31
|
+
expect(a.label).to be_a_relation_containing('resource A')
|
32
|
+
expect(b.label).to be_a_relation_containing('resource B')
|
33
33
|
|
34
34
|
b.in_resource = a
|
35
35
|
expect(b.in_resource).to eq [a]
|
36
|
-
expect(a.label).to
|
37
|
-
expect(b.label).to
|
36
|
+
expect(a.label).to be_a_relation_containing('resource A')
|
37
|
+
expect(b.label).to be_a_relation_containing('resource B')
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -46,7 +46,7 @@ describe 'reciprocal properties' do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
let (:b) do
|
49
|
-
p = DummyResourceB.new(RDF::URI('http://example.com/b'),a)
|
49
|
+
p = DummyResourceB.new(RDF::URI('http://example.com/b'), a)
|
50
50
|
p.label = 'resource B'
|
51
51
|
p
|
52
52
|
end
|
@@ -57,13 +57,13 @@ describe 'reciprocal properties' do
|
|
57
57
|
|
58
58
|
a.has_resource = b
|
59
59
|
expect(a.has_resource).to eq [b]
|
60
|
-
expect(a.label).to
|
61
|
-
expect(b.label).to
|
60
|
+
expect(a.label).to be_a_relation_containing('resource A')
|
61
|
+
expect(b.label).to be_a_relation_containing('resource B')
|
62
62
|
|
63
63
|
b.in_resource = a
|
64
64
|
expect(b.in_resource).to eq [a]
|
65
|
-
expect(a.label).to
|
66
|
-
expect(b.label).to
|
65
|
+
expect(a.label).to be_a_relation_containing('resource A')
|
66
|
+
expect(b.label).to be_a_relation_containing('resource B')
|
67
67
|
end
|
68
68
|
end
|
69
|
-
end
|
69
|
+
end
|
data/spec/support/matchers.rb
CHANGED
@@ -4,7 +4,19 @@ require 'spec_helper'
|
|
4
4
|
RSpec::Matchers.define :be_a_relation_containing do |*expected|
|
5
5
|
match do |actual|
|
6
6
|
expect(actual.class).to eq ActiveTriples::Relation
|
7
|
-
|
7
|
+
|
8
|
+
actual_terms = actual.map { |i| i.respond_to?(:to_term) ? i.to_term : i }
|
9
|
+
exp_terms = expected.map { |i| i.respond_to?(:to_term) ? i.to_term : i }
|
10
|
+
|
11
|
+
expect(actual_terms).to contain_exactly(*exp_terms)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :have_rdf_subject do |expected|
|
17
|
+
match do |actual|
|
18
|
+
expect(actual).to be_a ActiveTriples::RDFSource
|
19
|
+
expect(actual.to_term).to eq expected.to_term
|
8
20
|
true
|
9
21
|
end
|
10
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active-triples
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Johnson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-08-
|
12
|
+
date: 2016-08-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rdf
|
@@ -258,6 +258,8 @@ files:
|
|
258
258
|
- lib/active_triples/resource.rb
|
259
259
|
- lib/active_triples/schema.rb
|
260
260
|
- lib/active_triples/undefined_property_error.rb
|
261
|
+
- lib/active_triples/util/buffered_transaction.rb
|
262
|
+
- lib/active_triples/util/extended_bounded_description.rb
|
261
263
|
- lib/active_triples/version.rb
|
262
264
|
- spec/active_triples/configurable_spec.rb
|
263
265
|
- spec/active_triples/configuration_spec.rb
|
@@ -279,6 +281,8 @@ files:
|
|
279
281
|
- spec/active_triples/resource_spec.rb
|
280
282
|
- spec/active_triples/schema_spec.rb
|
281
283
|
- spec/active_triples/undefined_property_error_spec.rb
|
284
|
+
- spec/active_triples/util/buffered_transaction_spec.rb
|
285
|
+
- spec/active_triples/util/extended_bounded_description_spec.rb
|
282
286
|
- spec/active_triples/value_error_spec.rb
|
283
287
|
- spec/active_triples_spec.rb
|
284
288
|
- spec/integration/dummies/dummy_resource_a.rb
|
@@ -311,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
311
315
|
version: '0'
|
312
316
|
requirements: []
|
313
317
|
rubyforge_project:
|
314
|
-
rubygems_version: 2.
|
318
|
+
rubygems_version: 2.5.1
|
315
319
|
signing_key:
|
316
320
|
specification_version: 4
|
317
321
|
summary: RDF graphs in ActiveModel wrappers.
|