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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -9
  3. data/CHANGES.md +69 -0
  4. data/Gemfile +0 -2
  5. data/Guardfile +1 -2
  6. data/active-triples.gemspec +3 -3
  7. data/lib/active/triples.rb +1 -0
  8. data/lib/active_triples.rb +4 -0
  9. data/lib/active_triples/configurable.rb +3 -1
  10. data/lib/active_triples/configuration.rb +1 -0
  11. data/lib/active_triples/configuration/item.rb +1 -0
  12. data/lib/active_triples/configuration/item_factory.rb +1 -0
  13. data/lib/active_triples/configuration/merge_item.rb +5 -2
  14. data/lib/active_triples/extension_strategy.rb +1 -0
  15. data/lib/active_triples/identifiable.rb +1 -0
  16. data/lib/active_triples/list.rb +2 -0
  17. data/lib/active_triples/nested_attributes.rb +1 -1
  18. data/lib/active_triples/node_config.rb +5 -3
  19. data/lib/active_triples/persistable.rb +1 -0
  20. data/lib/active_triples/persistence_strategies/parent_strategy.rb +104 -29
  21. data/lib/active_triples/persistence_strategies/persistence_strategy.rb +15 -7
  22. data/lib/active_triples/persistence_strategies/repository_strategy.rb +26 -22
  23. data/lib/active_triples/properties.rb +84 -6
  24. data/lib/active_triples/property.rb +35 -4
  25. data/lib/active_triples/property_builder.rb +38 -4
  26. data/lib/active_triples/rdf_source.rb +225 -75
  27. data/lib/active_triples/reflection.rb +42 -3
  28. data/lib/active_triples/relation.rb +330 -73
  29. data/lib/active_triples/repositories.rb +4 -2
  30. data/lib/active_triples/resource.rb +1 -0
  31. data/lib/active_triples/schema.rb +1 -0
  32. data/lib/active_triples/undefined_property_error.rb +27 -0
  33. data/lib/active_triples/version.rb +2 -1
  34. data/spec/active_triples/configurable_spec.rb +3 -2
  35. data/spec/active_triples/configuration_spec.rb +2 -1
  36. data/spec/active_triples/extension_strategy_spec.rb +2 -1
  37. data/spec/active_triples/identifiable_spec.rb +7 -11
  38. data/spec/active_triples/list_spec.rb +1 -4
  39. data/spec/active_triples/nested_attributes_spec.rb +4 -3
  40. data/spec/active_triples/persistable_spec.rb +4 -1
  41. data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +141 -11
  42. data/spec/active_triples/persistence_strategies/persistence_strategy_spec.rb +1 -0
  43. data/spec/active_triples/persistence_strategies/repository_strategy_spec.rb +32 -17
  44. data/spec/active_triples/properties_spec.rb +68 -33
  45. data/spec/active_triples/property_builder_spec.rb +36 -0
  46. data/spec/active_triples/property_spec.rb +15 -1
  47. data/spec/active_triples/rdf_source_spec.rb +544 -6
  48. data/spec/active_triples/reflection_spec.rb +78 -0
  49. data/spec/active_triples/relation_spec.rb +505 -3
  50. data/spec/active_triples/repositories_spec.rb +3 -1
  51. data/spec/active_triples/resource_spec.rb +90 -147
  52. data/spec/active_triples/schema_spec.rb +3 -2
  53. data/spec/active_triples_spec.rb +1 -0
  54. data/spec/integration/dummies/dummy_resource_a.rb +6 -0
  55. data/spec/integration/dummies/dummy_resource_b.rb +6 -0
  56. data/spec/integration/parent_persistence_spec.rb +18 -0
  57. data/spec/integration/reciprocal_properties_spec.rb +69 -0
  58. data/spec/pragmatic_context_spec.rb +10 -8
  59. data/spec/spec_helper.rb +5 -0
  60. data/spec/support/active_model_lint.rb +4 -6
  61. data/spec/support/dummies/basic_persistable.rb +2 -11
  62. data/spec/support/matchers.rb +11 -0
  63. data/spec/support/shared_examples/persistence_strategy.rb +3 -16
  64. 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) }.to raise_error
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