active-triples 0.8.1 → 0.8.2
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 +8 -9
- data/CHANGES.md +69 -0
- data/Gemfile +0 -2
- data/Guardfile +1 -2
- data/active-triples.gemspec +3 -3
- data/lib/active/triples.rb +1 -0
- data/lib/active_triples.rb +4 -0
- data/lib/active_triples/configurable.rb +3 -1
- data/lib/active_triples/configuration.rb +1 -0
- data/lib/active_triples/configuration/item.rb +1 -0
- data/lib/active_triples/configuration/item_factory.rb +1 -0
- data/lib/active_triples/configuration/merge_item.rb +5 -2
- data/lib/active_triples/extension_strategy.rb +1 -0
- data/lib/active_triples/identifiable.rb +1 -0
- data/lib/active_triples/list.rb +2 -0
- data/lib/active_triples/nested_attributes.rb +1 -1
- data/lib/active_triples/node_config.rb +5 -3
- data/lib/active_triples/persistable.rb +1 -0
- data/lib/active_triples/persistence_strategies/parent_strategy.rb +104 -29
- data/lib/active_triples/persistence_strategies/persistence_strategy.rb +15 -7
- data/lib/active_triples/persistence_strategies/repository_strategy.rb +26 -22
- data/lib/active_triples/properties.rb +84 -6
- data/lib/active_triples/property.rb +35 -4
- data/lib/active_triples/property_builder.rb +38 -4
- data/lib/active_triples/rdf_source.rb +225 -75
- data/lib/active_triples/reflection.rb +42 -3
- data/lib/active_triples/relation.rb +330 -73
- data/lib/active_triples/repositories.rb +4 -2
- data/lib/active_triples/resource.rb +1 -0
- data/lib/active_triples/schema.rb +1 -0
- data/lib/active_triples/undefined_property_error.rb +27 -0
- data/lib/active_triples/version.rb +2 -1
- data/spec/active_triples/configurable_spec.rb +3 -2
- data/spec/active_triples/configuration_spec.rb +2 -1
- data/spec/active_triples/extension_strategy_spec.rb +2 -1
- data/spec/active_triples/identifiable_spec.rb +7 -11
- data/spec/active_triples/list_spec.rb +1 -4
- data/spec/active_triples/nested_attributes_spec.rb +4 -3
- data/spec/active_triples/persistable_spec.rb +4 -1
- data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +141 -11
- data/spec/active_triples/persistence_strategies/persistence_strategy_spec.rb +1 -0
- data/spec/active_triples/persistence_strategies/repository_strategy_spec.rb +32 -17
- data/spec/active_triples/properties_spec.rb +68 -33
- data/spec/active_triples/property_builder_spec.rb +36 -0
- data/spec/active_triples/property_spec.rb +15 -1
- data/spec/active_triples/rdf_source_spec.rb +544 -6
- data/spec/active_triples/reflection_spec.rb +78 -0
- data/spec/active_triples/relation_spec.rb +505 -3
- data/spec/active_triples/repositories_spec.rb +3 -1
- data/spec/active_triples/resource_spec.rb +90 -147
- data/spec/active_triples/schema_spec.rb +3 -2
- data/spec/active_triples_spec.rb +1 -0
- data/spec/integration/dummies/dummy_resource_a.rb +6 -0
- data/spec/integration/dummies/dummy_resource_b.rb +6 -0
- data/spec/integration/parent_persistence_spec.rb +18 -0
- data/spec/integration/reciprocal_properties_spec.rb +69 -0
- data/spec/pragmatic_context_spec.rb +10 -8
- data/spec/spec_helper.rb +5 -0
- data/spec/support/active_model_lint.rb +4 -6
- data/spec/support/dummies/basic_persistable.rb +2 -11
- data/spec/support/matchers.rb +11 -0
- data/spec/support/shared_examples/persistence_strategy.rb +3 -16
- metadata +20 -13
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveTriples::Reflection do
|
5
|
+
subject { klass.new }
|
6
|
+
|
7
|
+
let(:klass) { Class.new { include ActiveTriples::Reflection } }
|
8
|
+
|
9
|
+
let(:config_hash) do
|
10
|
+
{ 'moomin' => double('moomin config'),
|
11
|
+
'snorkmaiden' => double('snorkmaiden config') }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#reflections' do
|
15
|
+
it 'gives reflections for the instance' do
|
16
|
+
expect(subject.reflections).to eq klass
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.properties=' do
|
21
|
+
it 'sets properties' do
|
22
|
+
expect { klass.properties = config_hash }
|
23
|
+
.to change { klass._active_triples_config }.to config_hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.properties' do
|
28
|
+
it 'gets the set properties' do
|
29
|
+
klass.properties = config_hash
|
30
|
+
|
31
|
+
expect(klass.properties).to eq config_hash
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.has_property?' do
|
36
|
+
before { klass.properties = config_hash }
|
37
|
+
|
38
|
+
it 'returns true for properties it has' do
|
39
|
+
klass._active_triples_config.each do |property, _|
|
40
|
+
expect(klass).to have_property property
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'coerces to a string' do
|
45
|
+
klass._active_triples_config.each do |property, _|
|
46
|
+
expect(klass).to have_property property.to_sym
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns false for unregistered properties' do
|
51
|
+
expect(klass).not_to have_property 'moominmama'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.reflect_on_property' do
|
56
|
+
before { klass.properties = config_hash }
|
57
|
+
|
58
|
+
it 'gets the config for the requested property' do
|
59
|
+
klass._active_triples_config.each do |property, config|
|
60
|
+
expect(klass.reflect_on_property(property)).to eq config
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'coerces to a string' do
|
65
|
+
klass._active_triples_config.each do |property, config|
|
66
|
+
expect(klass.reflect_on_property(property.to_sym)).to eq config
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises an error on unregistered properties' do
|
71
|
+
expect { klass.reflect_on_property(:fake) }.to raise_error do |err|
|
72
|
+
expect(err).to be_a ActiveTriples::UndefinedPropertyError
|
73
|
+
expect(err.klass).to eq klass
|
74
|
+
expect(err.property).to eq :fake.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,7 +1,421 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'spec_helper'
|
2
3
|
require 'rdf/isomorphic'
|
3
4
|
|
4
5
|
describe ActiveTriples::Relation do
|
6
|
+
let(:parent_resource) { double("parent resource", reflections: {}) }
|
7
|
+
let(:value_args) { double("value args", last: {}) }
|
8
|
+
|
9
|
+
let(:uri) { RDF::URI('http://example.org/moomin') }
|
10
|
+
|
11
|
+
subject { described_class.new(parent_resource, value_args) }
|
12
|
+
|
13
|
+
shared_context 'with URI property' do
|
14
|
+
subject { described_class.new(parent_resource, [property] ) }
|
15
|
+
let(:property) { uri }
|
16
|
+
end
|
17
|
+
|
18
|
+
shared_context 'with symbol property' do
|
19
|
+
subject { described_class.new(parent_resource, [property] ) }
|
20
|
+
let(:property) { :moomin }
|
21
|
+
let(:reflections) do
|
22
|
+
Class.new do
|
23
|
+
include ActiveTriples::RDFSource
|
24
|
+
property :moomin, predicate: RDF::URI('http://example.org/moomin')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
before do
|
29
|
+
allow(parent_resource).to receive(:reflections).and_return(reflections)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
shared_context 'with unregistered property' do
|
34
|
+
subject { described_class.new(parent_resource, [property] ) }
|
35
|
+
let(:property) { :moomin }
|
36
|
+
let(:reflections) { Class.new { include ActiveTriples::RDFSource } }
|
37
|
+
|
38
|
+
before do
|
39
|
+
allow(parent_resource).to receive(:reflections).and_return(reflections)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#build' do
|
44
|
+
include_context 'with symbol property'
|
45
|
+
|
46
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
47
|
+
|
48
|
+
it 'returns a new child node' do
|
49
|
+
expect(subject.build).to be_a ActiveTriples::RDFSource
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'adds new child node to relation' do
|
53
|
+
expect { subject.build }.to change { subject.count }.by(1)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'builds child as new blank node by default' do
|
57
|
+
expect(subject.build).to be_node
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'builds child with uri if given' do
|
61
|
+
uri = 'http://example.com/moomin'
|
62
|
+
expect(subject.build(id: uri)).to be_uri
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with configured properties' do
|
66
|
+
include_context 'with symbol property' do
|
67
|
+
before do
|
68
|
+
reflections.property :moomin,
|
69
|
+
predicate: RDF::Vocab::DC.relation,
|
70
|
+
class_name: 'WithTitle'
|
71
|
+
class WithTitle
|
72
|
+
include ActiveTriples::RDFSource
|
73
|
+
property :title, predicate: RDF::Vocab::DC.title
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
after { Object.send(:remove_const, :WithTitle) }
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'sets attributes for built node' do
|
81
|
+
attributes = { title: 'moomin' }
|
82
|
+
|
83
|
+
expect(subject.build(attributes))
|
84
|
+
.to have_attributes(title: ['moomin'])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#delete' do
|
90
|
+
include_context 'with symbol property'
|
91
|
+
|
92
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
93
|
+
|
94
|
+
it 'handles a non-existent value' do
|
95
|
+
expect { subject.delete(1) }.not_to change { subject.to_a }
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with values' do
|
99
|
+
before { subject << values }
|
100
|
+
|
101
|
+
let(:node) { RDF::Node.new(:node) }
|
102
|
+
let(:uri) { RDF.Property }
|
103
|
+
let(:values) { ['1', 1, :one, false, DateTime.now, node, uri] }
|
104
|
+
|
105
|
+
it 'handles a non-existent value' do
|
106
|
+
expect { subject.delete('blah') }.not_to change { subject.to_a }
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'deletes a matched value' do
|
110
|
+
expect { subject.delete(values.first) }
|
111
|
+
.to change { subject.to_a }
|
112
|
+
.to contain_exactly(*values[1..-1])
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'deletes a URI value' do
|
116
|
+
values.delete(uri)
|
117
|
+
expect { subject.delete(uri) }
|
118
|
+
.to change { subject.to_a }
|
119
|
+
.to contain_exactly(*values)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'deletes a node value' do
|
123
|
+
values.delete(node)
|
124
|
+
expect { subject.delete(node) }
|
125
|
+
.to change { subject.to_a }
|
126
|
+
.to contain_exactly(*values)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'deletes a token value' do
|
130
|
+
values.delete(:one)
|
131
|
+
expect { subject.delete(:one) }
|
132
|
+
.to change { subject.to_a }
|
133
|
+
.to contain_exactly(*values)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#delete?' do
|
139
|
+
include_context 'with symbol property'
|
140
|
+
|
141
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
142
|
+
|
143
|
+
it 'gives nil for non-existant value' do
|
144
|
+
expect(subject.delete?(1)).to be_nil
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'returns value when deleted' do
|
148
|
+
subject.set(1)
|
149
|
+
expect(subject.delete?(1)).to eq 1
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'deletes existing values' do
|
153
|
+
subject.set(1)
|
154
|
+
expect { subject.delete?(1) }
|
155
|
+
.to change { subject.to_a }.to be_empty
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe '#subtract' do
|
160
|
+
include_context 'with symbol property'
|
161
|
+
|
162
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
163
|
+
|
164
|
+
it 'subtracts values as arguments' do
|
165
|
+
subject.set([1,2,3])
|
166
|
+
expect { subject.subtract(2,3) }
|
167
|
+
.to change { subject.to_a }.to contain_exactly(1)
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'subtracts values as an enumerable' do
|
171
|
+
subject.set([1,2,3])
|
172
|
+
expect { subject.subtract([2,3]) }
|
173
|
+
.to change { subject.to_a }.to contain_exactly(1)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'subtracts token values' do
|
177
|
+
subject.set([:one, :two, :three])
|
178
|
+
expect { subject.subtract([:two, :three]) }
|
179
|
+
.to change { subject.to_a }.to contain_exactly(:one)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe '#swap' do
|
184
|
+
include_context 'with symbol property'
|
185
|
+
|
186
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
187
|
+
|
188
|
+
it 'returns nil when the value is not present' do
|
189
|
+
expect(subject.swap(1, 2)).to be_nil
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'does not change contents for non-existent value' do
|
193
|
+
expect { subject.swap(1, 2) }.not_to change { subject.to_a }
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'swaps the value' do
|
197
|
+
values = [1, 2, 3]
|
198
|
+
subject.set(values)
|
199
|
+
expect { subject.swap(1, 4) }
|
200
|
+
.to change { subject.to_a }.to contain_exactly(2, 3, 4)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe '#clear' do
|
205
|
+
include_context 'with symbol property'
|
206
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
207
|
+
|
208
|
+
context 'with values' do
|
209
|
+
before do
|
210
|
+
subject.parent << [subject.parent.rdf_subject,
|
211
|
+
subject.predicate,
|
212
|
+
'moomin']
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'clears the relation' do
|
216
|
+
expect { subject.clear }.to change { subject.result }
|
217
|
+
.from(['moomin']).to([])
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'deletes statements from parent' do
|
221
|
+
query_pattern = [subject.parent.rdf_subject, subject.predicate, nil]
|
222
|
+
|
223
|
+
expect { subject.clear }
|
224
|
+
.to change { subject.parent.query(query_pattern) }.to([])
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'is a no-op when relation is empty' do
|
229
|
+
subject.parent << [subject.parent.rdf_subject, RDF.type, 'moomin']
|
230
|
+
expect { subject.clear }.not_to change { subject.parent.statements.to_a }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe '#<<' do
|
235
|
+
include_context 'with symbol property'
|
236
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
237
|
+
|
238
|
+
it 'adds a value' do
|
239
|
+
expect { subject << :moomin }
|
240
|
+
.to change { subject.to_a }.to contain_exactly(:moomin)
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'adds multiple values' do
|
244
|
+
values = [:moomin, :snork]
|
245
|
+
expect { subject << values }
|
246
|
+
.to change { subject.to_a }.to contain_exactly(*values)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "#predicate" do
|
251
|
+
context 'when the property is an RDF::Term' do
|
252
|
+
include_context 'with URI property'
|
253
|
+
|
254
|
+
it 'returns the specified RDF::Term' do
|
255
|
+
expect(subject.predicate).to eq uri
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context 'when the property is a symbol' do
|
260
|
+
include_context 'with symbol property'
|
261
|
+
|
262
|
+
it 'returns the reflected property' do
|
263
|
+
expect(subject.predicate).to eq uri
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context 'when the symbol property is unregistered' do
|
268
|
+
include_context 'with unregistered property'
|
269
|
+
it 'returns nil' do
|
270
|
+
expect(subject.predicate).to be_nil
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "#property" do
|
276
|
+
context 'when the property is an RDF::Term' do
|
277
|
+
include_context 'with URI property'
|
278
|
+
|
279
|
+
it 'returns the specified RDF::Term' do
|
280
|
+
expect(subject.property).to eq property
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context 'when the property is a symbol' do
|
285
|
+
include_context 'with symbol property'
|
286
|
+
|
287
|
+
it 'returns the property symbol' do
|
288
|
+
expect(subject.property).to eq property
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context 'when the symbol property is unregistered' do
|
293
|
+
include_context 'with unregistered property'
|
294
|
+
|
295
|
+
it 'returns the property symbol' do
|
296
|
+
expect(subject.property).to eq property
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe '#first_or_create' do
|
302
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
303
|
+
|
304
|
+
context 'with symbol' do
|
305
|
+
include_context 'with symbol property'
|
306
|
+
|
307
|
+
it 'creates a new node' do
|
308
|
+
expect { subject.first_or_create }.to change { subject.count }.by(1)
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'returns existing node if present' do
|
312
|
+
node = subject.build
|
313
|
+
expect(subject.first_or_create).to eq node
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'does not create a new node when one exists' do
|
317
|
+
subject.build
|
318
|
+
expect { subject.first_or_create }.not_to change { subject.count }
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'returns literal value if appropriate' do
|
322
|
+
subject << literal = 'moomin'
|
323
|
+
expect(subject.first_or_create).to eq literal
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe '#result' do
|
329
|
+
context 'with nil predicate' do
|
330
|
+
include_context 'with unregistered property'
|
331
|
+
|
332
|
+
it 'is empty' do
|
333
|
+
expect(subject.result).to contain_exactly()
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'with predicate' do
|
338
|
+
include_context 'with symbol property' do
|
339
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'is empty' do
|
343
|
+
expect(subject.result).to contain_exactly()
|
344
|
+
end
|
345
|
+
|
346
|
+
context 'with values' do
|
347
|
+
before do
|
348
|
+
values.each do |value|
|
349
|
+
subject.parent << [subject.parent.rdf_subject, uri, value]
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
let(:values) { ['Comet in Moominland', 'Finn Family Moomintroll'] }
|
354
|
+
let(:node) { RDF::Node.new }
|
355
|
+
|
356
|
+
it 'contain values' do
|
357
|
+
expect(subject.result).to contain_exactly(*values)
|
358
|
+
end
|
359
|
+
|
360
|
+
context 'with castable values' do
|
361
|
+
let(:values) do
|
362
|
+
[uri, RDF::URI('http://ex.org/too-ticky'), RDF::Node.new]
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'casts Resource values' do
|
366
|
+
expect(subject.result)
|
367
|
+
.to contain_exactly(a_kind_of(ActiveTriples::Resource),
|
368
|
+
a_kind_of(ActiveTriples::Resource),
|
369
|
+
a_kind_of(ActiveTriples::Resource))
|
370
|
+
end
|
371
|
+
|
372
|
+
it 'cast values have correct URI' do
|
373
|
+
expect(subject.result.map(&:rdf_subject))
|
374
|
+
.to contain_exactly(*values)
|
375
|
+
end
|
376
|
+
|
377
|
+
context 'and persistence_strategy is configured' do
|
378
|
+
before do
|
379
|
+
reflections
|
380
|
+
.property :moomin,
|
381
|
+
predicate: RDF::URI('http://example.org/moomin'),
|
382
|
+
persist_to: ActiveTriples::RepositoryStrategy
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'assigns persistence strategy' do
|
386
|
+
subject.result.each do |node|
|
387
|
+
expect(node.persistence_strategy)
|
388
|
+
.to be_a ActiveTriples::RepositoryStrategy
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
context 'and #cast? is false' do
|
394
|
+
let(:values) do
|
395
|
+
[uri, RDF::URI('http://ex.org/too-ticky'), RDF::Node.new,
|
396
|
+
'moomin', Date.today]
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'does not cast results' do
|
400
|
+
allow(subject).to receive(:cast?).and_return(false)
|
401
|
+
expect(subject.result).to contain_exactly(*values)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
context 'when #return_literals? is true' do
|
406
|
+
let(:values) do
|
407
|
+
[RDF::Literal('moomin'), RDF::Literal(Date.today)]
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'does not cast results' do
|
411
|
+
allow(subject).to receive(:return_literals?).and_return(true)
|
412
|
+
expect(subject.result).to contain_exactly(*values)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
5
419
|
|
6
420
|
describe "#rdf_subject" do
|
7
421
|
let(:parent_resource) { double("parent resource", reflections: {}) }
|
@@ -10,32 +424,120 @@ describe ActiveTriples::Relation do
|
|
10
424
|
|
11
425
|
context "when relation has 0 value arguments" do
|
12
426
|
before { subject.value_arguments = double(length: 0) }
|
427
|
+
|
13
428
|
it "should raise an error" do
|
14
|
-
expect { subject.send(:rdf_subject) }.to raise_error
|
429
|
+
expect { subject.send(:rdf_subject) }.to raise_error ArgumentError
|
15
430
|
end
|
16
431
|
end
|
432
|
+
|
17
433
|
context "when term has 1 value argument" do
|
18
434
|
before do
|
19
435
|
allow(subject.parent).to receive(:rdf_subject) { "parent subject" }
|
20
436
|
subject.value_arguments = double(length: 1)
|
21
437
|
end
|
438
|
+
|
22
439
|
it "should call `rdf_subject' on the parent" do
|
23
440
|
expect(subject.send(:rdf_subject) ).to eq "parent subject"
|
24
441
|
end
|
442
|
+
|
25
443
|
it " is a private method" do
|
26
444
|
expect { subject.rdf_subject }.to raise_error NoMethodError
|
27
445
|
end
|
28
446
|
end
|
447
|
+
|
29
448
|
context "when relation has 2 value arguments" do
|
30
449
|
before { subject.value_arguments = double(length: 2, first: "first") }
|
450
|
+
|
31
451
|
it "should return the first value argument" do
|
32
452
|
expect(subject.send(:rdf_subject) ).to eq "first"
|
33
453
|
end
|
34
454
|
end
|
455
|
+
|
35
456
|
context "when relation has 3 value arguments" do
|
36
457
|
before { subject.value_arguments = double(length: 3) }
|
458
|
+
|
37
459
|
it "should raise an error" do
|
38
|
-
expect { subject.send(:rdf_subject)
|
460
|
+
expect { subject.send(:rdf_subject) }.to raise_error ArgumentError
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
describe '#size' do
|
466
|
+
context 'with predicate' do
|
467
|
+
include_context 'with symbol property' do
|
468
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
469
|
+
end
|
470
|
+
|
471
|
+
context 'with values' do
|
472
|
+
let(:values) { ['Comet in Moominland', 'Finn Family Moomintroll'] }
|
473
|
+
before do
|
474
|
+
values.each do |value|
|
475
|
+
subject.parent << [subject.parent.rdf_subject, uri, value]
|
476
|
+
end
|
477
|
+
end
|
478
|
+
it "returns the size of the result" do
|
479
|
+
expect(subject.size).to eq 2
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
describe '#set' do
|
486
|
+
include_context 'with unregistered property'
|
487
|
+
|
488
|
+
it 'raises UndefinedPropertyError' do
|
489
|
+
expect { subject.set('x') }
|
490
|
+
.to raise_error ActiveTriples::UndefinedPropertyError
|
491
|
+
end
|
492
|
+
|
493
|
+
context 'with predicate' do
|
494
|
+
include_context 'with symbol property' do
|
495
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
496
|
+
end
|
497
|
+
|
498
|
+
it 'sets a value' do
|
499
|
+
expect { subject.set(:moomin) }
|
500
|
+
.to change { subject.to_a }.to contain_exactly(:moomin)
|
501
|
+
end
|
502
|
+
|
503
|
+
it 'sets mulitple values' do
|
504
|
+
values = [:moomin, :snork]
|
505
|
+
expect { subject.set(values) }
|
506
|
+
.to change { subject.to_a }.to contain_exactly(*values)
|
507
|
+
end
|
508
|
+
|
509
|
+
context 'and persistence config' do
|
510
|
+
before do
|
511
|
+
reflections
|
512
|
+
.property :moomin,
|
513
|
+
predicate: RDF::URI('http://example.org/moomin'),
|
514
|
+
persist_to: ActiveTriples::RepositoryStrategy
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'returns values with persistence strategy set' do
|
518
|
+
expect(subject.set(RDF::Node.new).map(&:persistence_strategy))
|
519
|
+
.to contain_exactly(an_instance_of(ActiveTriples::RepositoryStrategy))
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
describe '#join' do
|
526
|
+
context 'with predicate' do
|
527
|
+
include_context 'with symbol property' do
|
528
|
+
let(:parent_resource) { ActiveTriples::Resource.new }
|
529
|
+
end
|
530
|
+
|
531
|
+
context 'with values' do
|
532
|
+
let(:values) { ['Comet in Moominland', 'Finn Family Moomintroll'] }
|
533
|
+
before do
|
534
|
+
values.each do |value|
|
535
|
+
subject.parent << [subject.parent.rdf_subject, uri, value]
|
536
|
+
end
|
537
|
+
end
|
538
|
+
it "returns joined strings" do
|
539
|
+
expect(subject.join(", ")).to eq "Comet in Moominland, Finn Family Moomintroll"
|
540
|
+
end
|
39
541
|
end
|
40
542
|
end
|
41
543
|
end
|
@@ -65,6 +567,7 @@ describe ActiveTriples::Relation do
|
|
65
567
|
expect(subject.send(:valid_datatype?, true)).to be true
|
66
568
|
end
|
67
569
|
end
|
570
|
+
|
68
571
|
context "the value is a Resource" do
|
69
572
|
after { Object.send(:remove_const, :DummyResource) }
|
70
573
|
let(:resource) { DummyResource.new }
|
@@ -99,5 +602,4 @@ describe ActiveTriples::Relation do
|
|
99
602
|
end
|
100
603
|
end
|
101
604
|
end
|
102
|
-
|
103
605
|
end
|