active-triples 0.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.
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+ describe ActiveTriples::Properties do
3
+ before do
4
+ class DummyProperties
5
+ extend ActiveTriples::Properties
6
+ end
7
+ end
8
+
9
+ after do
10
+ Object.send(:remove_const, "DummyProperties")
11
+ end
12
+
13
+ describe '#map_predicates' do
14
+ before do
15
+ DummyProperties.map_predicates do |map|
16
+ map.title(:in => RDF::DC, :class_name => RDF::Literal) do |index|
17
+ index.as :facetable, :searchable
18
+ end
19
+ end
20
+ end
21
+
22
+ it 'should set a property' do
23
+ expect(DummyProperties.properties).to include :title
24
+ end
25
+
26
+ it "should set index behaviors" do
27
+ expect(DummyProperties.properties[:title][:behaviors]).to eq [:facetable, :searchable]
28
+ end
29
+
30
+ it "should set a class name" do
31
+ expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
32
+ end
33
+ end
34
+
35
+ describe '#property' do
36
+ it 'should set a property' do
37
+ DummyProperties.property :title, :predicate => RDF::DC.title
38
+ expect(DummyProperties.properties).to include :title
39
+ end
40
+
41
+ it 'should set index behaviors' do
42
+ DummyProperties.property :title, :predicate => RDF::DC.title do |index|
43
+ index.as :facetable, :searchable
44
+ end
45
+ expect(DummyProperties.properties[:title][:behaviors]).to eq [:facetable, :searchable]
46
+ end
47
+
48
+ it 'should set class name' do
49
+ DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => RDF::Literal
50
+ expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
51
+ end
52
+
53
+ it "should constantize string class names" do
54
+ DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => "RDF::Literal"
55
+ expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
56
+ end
57
+
58
+ it "should keep strings which it can't constantize as strings" do
59
+ DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => "FakeClassName"
60
+ expect(DummyProperties.properties[:title][:class_name]).to eq "FakeClassName"
61
+ end
62
+
63
+ end
64
+
65
+ context "when using a subclass" do
66
+ before do
67
+ DummyProperties.property :title, :predicate => RDF::DC.title
68
+ class DummySubClass < DummyProperties
69
+ property :source, :predicate => RDF::DC11[:source]
70
+ end
71
+ end
72
+
73
+ after do
74
+ Object.send(:remove_const, "DummySubClass")
75
+ end
76
+
77
+ it 'should carry properties from superclass' do
78
+ expect(DummySubClass.properties.keys).to eq ["title", "source"]
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+ describe ActiveTriples::Repositories do
3
+ subject {ActiveTriples::Repositories}
4
+
5
+ after(:each) do
6
+ subject.clear_repositories!
7
+ subject.add_repository :default, RDF::Repository.new
8
+ subject.add_repository :vocabs, RDF::Repository.new
9
+ end
10
+
11
+ describe '#add_repositories' do
12
+ it 'should accept a new repository' do
13
+ subject.add_repository :name, RDF::Repository.new
14
+ expect(subject.repositories).to include :name
15
+ end
16
+ it 'should throw an error if passed something that is not a repository' do
17
+ expect{subject.add_repository :name, :not_a_repo}.to raise_error
18
+ end
19
+ end
20
+
21
+ describe '#clear_repositories!' do
22
+ it 'should empty the repositories list' do
23
+ subject.clear_repositories!
24
+ expect(subject.repositories).to be_empty
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,447 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveTriples::Resource do
4
+ it_behaves_like 'an ActiveModel'
5
+ before do
6
+ class DummyLicense < ActiveTriples::Resource
7
+ property :title, :predicate => RDF::DC.title
8
+ end
9
+
10
+ class DummyResource < ActiveTriples::Resource
11
+ configure :type => RDF::URI('http://example.org/SomeClass')
12
+ property :license, :predicate => RDF::DC.license, :class_name => DummyLicense
13
+ property :title, :predicate => RDF::DC.title
14
+ end
15
+ end
16
+ after do
17
+ Object.send(:remove_const, "DummyResource") if Object
18
+ Object.send(:remove_const, "DummyLicense") if Object
19
+ end
20
+
21
+ subject { DummyResource.new }
22
+
23
+ describe 'rdf_subject' do
24
+ it "should be a blank node if we haven't set it" do
25
+ expect(subject.rdf_subject.node?).to be_true
26
+ end
27
+
28
+ it "should be settable" do
29
+ subject.set_subject! RDF::URI('http://example.org/moomin')
30
+ expect(subject.rdf_subject).to eq RDF::URI('http://example.org/moomin')
31
+ end
32
+
33
+ it "should raise an error when setting to an invalid uri" do
34
+ expect{ subject.set_subject!('not_a_uri') }.to raise_error "could not make a valid RDF::URI from not_a_uri"
35
+ end
36
+
37
+ describe 'when changing subject' do
38
+ before do
39
+ subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland'))
40
+ subject << RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject)
41
+ subject << RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land')
42
+ subject.set_subject! RDF::URI('http://example.org/moomin')
43
+ end
44
+
45
+ it 'should update graph subjects' do
46
+ expect(subject.has_statement?(RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland')))).to be_true
47
+ end
48
+
49
+ it 'should update graph objects' do
50
+ expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject))).to be_true
51
+ end
52
+
53
+ it 'should leave other uris alone' do
54
+ expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land'))).to be_true
55
+ end
56
+ end
57
+
58
+ describe 'with URI subject' do
59
+ before do
60
+ subject.set_subject! RDF::URI('http://example.org/moomin')
61
+ end
62
+
63
+ it 'should not be settable' do
64
+ expect{ subject.set_subject! RDF::URI('http://example.org/moomin2') }.to raise_error
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#persisted?" do
70
+ context 'with a repository' do
71
+ before do
72
+ repository = RDF::Repository.new
73
+ subject.stub(:repository).and_return(repository)
74
+ end
75
+
76
+ context "when the object is new" do
77
+ it "should return false" do
78
+ expect(subject).not_to be_persisted
79
+ end
80
+ end
81
+
82
+ context "when it is saved" do
83
+ before do
84
+ subject.title = "bla"
85
+ subject.persist!
86
+ end
87
+
88
+ it "should return true" do
89
+ expect(subject).to be_persisted
90
+ end
91
+
92
+ context "and then modified" do
93
+ before do
94
+ subject.title = "newbla"
95
+ end
96
+
97
+ it "should return true" do
98
+ expect(subject).to be_persisted
99
+ end
100
+ end
101
+ context "and then reloaded" do
102
+ before do
103
+ subject.reload
104
+ end
105
+
106
+ it "should reset the title" do
107
+ expect(subject.title).to eq ["bla"]
108
+ end
109
+
110
+ it "should be persisted" do
111
+ expect(subject).to be_persisted
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#persist!" do
119
+ context "when the repository is set" do
120
+ context "and the item is not a blank node" do
121
+
122
+ subject {DummyResource.new("info:fedora/example:pid")}
123
+
124
+ before do
125
+ @repo = RDF::Repository.new
126
+ subject.class.stub(:repository).and_return(nil)
127
+ subject.stub(:repository).and_return(@repo)
128
+ subject.title = "bla"
129
+ subject.persist!
130
+ end
131
+
132
+ it "should persist to the repository" do
133
+ expect(@repo.statements.first).to eq subject.statements.first
134
+ end
135
+
136
+ it "should delete from the repository" do
137
+ subject.reload
138
+ expect(subject.title).to eq ["bla"]
139
+ subject.title = []
140
+ expect(subject.title).to eq []
141
+ subject.persist!
142
+ subject.reload
143
+ expect(subject.title).to eq []
144
+ expect(@repo.statements.to_a.length).to eq 1 # Only the type statement
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ describe '#destroy!' do
151
+ before do
152
+ subject.title = 'Creative Commons'
153
+ subject << RDF::Statement(RDF::DC.LicenseDocument, RDF::DC.title, 'LICENSE')
154
+ end
155
+
156
+ subject { DummyLicense.new('http://example.org/cc')}
157
+
158
+ it 'should return true' do
159
+ expect(subject.destroy!).to be_true
160
+ expect(subject.destroy).to be_true
161
+ end
162
+
163
+ it 'should delete the graph' do
164
+ subject.destroy
165
+ expect(subject).to be_empty
166
+ end
167
+
168
+ context 'with a parent' do
169
+ before do
170
+ parent.license = subject
171
+ end
172
+
173
+ let(:parent) do
174
+ DummyResource.new('http://example.org/moomi')
175
+ end
176
+
177
+ it 'should empty the graph and remove it from the parent' do
178
+ subject.destroy
179
+ expect(parent.license).to be_empty
180
+ end
181
+
182
+ it 'should remove its whole graph from the parent' do
183
+ subject.destroy
184
+ subject.each_statement do |s|
185
+ expect(parent.statements).not_to include s
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ describe 'attributes' do
192
+ before do
193
+ subject.license = license
194
+ subject.title = 'moomi'
195
+ end
196
+
197
+ let(:license) { DummyLicense.new('http://example.org/license') }
198
+
199
+ it 'should return an attributes hash' do
200
+ expect(subject.attributes).to be_a Hash
201
+ end
202
+
203
+ it 'should contain data' do
204
+ expect(subject.attributes['title']).to eq ['moomi']
205
+ end
206
+
207
+ it 'should contain child objects' do
208
+ expect(subject.attributes['license']).to eq [license]
209
+ end
210
+
211
+ context 'with unmodeled data' do
212
+ before do
213
+ subject << RDF::Statement(subject.rdf_subject, RDF::DC.contributor, 'Tove Jansson')
214
+ subject << RDF::Statement(subject.rdf_subject, RDF::DC.relation, RDF::URI('http://example.org/moomi'))
215
+ node = RDF::Node.new
216
+ subject << RDF::Statement(RDF::URI('http://example.org/moomi'), RDF::DC.relation, node)
217
+ subject << RDF::Statement(node, RDF::DC.title, 'bnode')
218
+ end
219
+
220
+ it 'should include data with URIs as attribute names' do
221
+ expect(subject.attributes[RDF::DC.contributor.to_s]).to eq ['Tove Jansson']
222
+ end
223
+
224
+ it 'should return generic Resources' do
225
+ expect(subject.attributes[RDF::DC.relation.to_s].first).to be_a ActiveTriples::Resource
226
+ end
227
+
228
+ it 'should build deep data for Resources' do
229
+ expect(subject.attributes[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
230
+ first.get_values(RDF::DC.title)).to eq ['bnode']
231
+ end
232
+
233
+ it 'should include deep data in serializable_hash' do
234
+ expect(subject.serializable_hash[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
235
+ first.get_values(RDF::DC.title)).to eq ['bnode']
236
+ end
237
+ end
238
+
239
+ describe 'attribute_serialization' do
240
+ describe '#to_json' do
241
+ it 'should return a string with correct objects' do
242
+ json_hash = JSON.parse(subject.to_json)
243
+ expect(json_hash['license'].first['id']).to eq license.rdf_subject.to_s
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ describe 'property methods' do
250
+ it 'should set and get properties' do
251
+ subject.title = 'Comet in Moominland'
252
+ expect(subject.title).to eq ['Comet in Moominland']
253
+ end
254
+ end
255
+
256
+ describe 'child nodes' do
257
+ it 'should return an object of the correct class when the value is a URI' do
258
+ subject.license = DummyLicense.new('http://example.org/license')
259
+ expect(subject.license.first).to be_kind_of DummyLicense
260
+ end
261
+
262
+ it 'should return an object with the correct URI when the value is a URI ' do
263
+ subject.license = DummyLicense.new('http://example.org/license')
264
+ expect(subject.license.first.rdf_subject).to eq RDF::URI("http://example.org/license")
265
+ end
266
+
267
+ it 'should return an object of the correct class when the value is a bnode' do
268
+ subject.license = DummyLicense.new
269
+ expect(subject.license.first).to be_kind_of DummyLicense
270
+ end
271
+ end
272
+
273
+ describe '#set_value' do
274
+ it 'should set a value in the graph' do
275
+ subject.set_value(RDF::DC.title, 'Comet in Moominland')
276
+ subject.query(:subject => subject.rdf_subject, :predicate => RDF::DC.title).each_statement do |s|
277
+ expect(s.object.to_s).to eq 'Comet in Moominland'
278
+ end
279
+ end
280
+
281
+ it 'should set a value in the when given a registered property symbol' do
282
+ subject.set_value(:title, 'Comet in Moominland')
283
+ expect(subject.title).to eq ['Comet in Moominland']
284
+ end
285
+
286
+ it "raise an error if the value is not a URI, Node, Literal, RdfResource, or string" do
287
+ expect{subject.set_value(RDF::DC.title, Object.new)}.to raise_error
288
+ end
289
+
290
+ it "should be able to accept a subject" do
291
+ expect{subject.set_value(RDF::URI("http://opaquenamespace.org/jokes"), RDF::DC.title, 'Comet in Moominland')}.not_to raise_error
292
+ expect(subject.query(:subject => RDF::URI("http://opaquenamespace.org/jokes"), :predicate => RDF::DC.title).statements.to_a.length).to eq 1
293
+ end
294
+ end
295
+ describe '#get_values' do
296
+ before do
297
+ subject.title = ['Comet in Moominland', "Finn Family Moomintroll"]
298
+ end
299
+
300
+ it 'should return values for a predicate uri' do
301
+ expect(subject.get_values(RDF::DC.title)).to eq ['Comet in Moominland', 'Finn Family Moomintroll']
302
+ end
303
+
304
+ it 'should return values for a registered predicate symbol' do
305
+ expect(subject.get_values(:title)).to eq ['Comet in Moominland', 'Finn Family Moomintroll']
306
+ end
307
+
308
+ it "should return values for other subjects if asked" do
309
+ expect(subject.get_values(RDF::URI("http://opaquenamespace.org/jokes"),:title)).to eq []
310
+ subject.set_value(RDF::URI("http://opaquenamespace.org/jokes"), RDF::DC.title, 'Comet in Moominland')
311
+ expect(subject.get_values(RDF::URI("http://opaquenamespace.org/jokes"),:title)).to eq ["Comet in Moominland"]
312
+ end
313
+ end
314
+
315
+ describe '#type' do
316
+ it 'should return the type configured on the parent class' do
317
+ expect(subject.type).to eq [DummyResource.type]
318
+ end
319
+
320
+ it 'should set the type' do
321
+ subject.type = RDF::URI('http://example.org/AnotherClass')
322
+ expect(subject.type).to eq [RDF::URI('http://example.org/AnotherClass')]
323
+ end
324
+
325
+ it 'should be the type in the graph' do
326
+ subject.query(:subject => subject.rdf_subject, :predicate => RDF.type).statements do |s|
327
+ expect(s.object).to eq RDF::URI('http://example.org/AnotherClass')
328
+ end
329
+ end
330
+ end
331
+
332
+ describe '#rdf_label' do
333
+ it 'should return an array of label values' do
334
+ expect(subject.rdf_label).to be_kind_of Array
335
+ end
336
+
337
+ it 'should return the default label values' do
338
+ subject.title = 'Comet in Moominland'
339
+ expect(subject.rdf_label).to eq ['Comet in Moominland']
340
+ end
341
+
342
+ it 'should prioritize configured label values' do
343
+ custom_label = RDF::URI('http://example.org/custom_label')
344
+ subject.class.configure :rdf_label => custom_label
345
+ subject << RDF::Statement(subject.rdf_subject, custom_label, RDF::Literal('New Label'))
346
+ subject.title = 'Comet in Moominland'
347
+ expect(subject.rdf_label).to eq ['New Label']
348
+ end
349
+ end
350
+
351
+ describe '#solrize' do
352
+ it 'should return a label for bnodes' do
353
+ expect(subject.solrize).to eq subject.rdf_label
354
+ end
355
+
356
+ it 'should return a string of the resource uri' do
357
+ subject.set_subject! 'http://example.org/moomin'
358
+ expect(subject.solrize).to eq 'http://example.org/moomin'
359
+ end
360
+ end
361
+
362
+ describe 'editing the graph' do
363
+ it 'should write properties when statements are added' do
364
+ subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
365
+ expect(subject.title).to include 'Comet in Moominland'
366
+ end
367
+
368
+ it 'should delete properties when statements are removed' do
369
+ subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
370
+ subject.delete RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
371
+ expect(subject.title).to eq []
372
+ end
373
+ end
374
+
375
+ describe 'big complex graphs' do
376
+ before do
377
+ class DummyPerson < ActiveTriples::Resource
378
+ configure :type => RDF::URI('http://example.org/Person')
379
+ property :name, :predicate => RDF::FOAF.name
380
+ property :publications, :predicate => RDF::FOAF.publications, :class_name => 'DummyDocument'
381
+ property :knows, :predicate => RDF::FOAF.knows, :class_name => DummyPerson
382
+ end
383
+
384
+ class DummyDocument < ActiveTriples::Resource
385
+ configure :type => RDF::URI('http://example.org/Document')
386
+ property :title, :predicate => RDF::DC.title
387
+ property :creator, :predicate => RDF::DC.creator, :class_name => 'DummyPerson'
388
+ end
389
+
390
+ DummyResource.property :item, :predicate => RDF::DC.relation, :class_name => DummyDocument
391
+ end
392
+
393
+ subject { DummyResource.new }
394
+
395
+ let (:document1) do
396
+ d = DummyDocument.new
397
+ d.title = 'Document One'
398
+ d
399
+ end
400
+
401
+ let (:document2) do
402
+ d = DummyDocument.new
403
+ d.title = 'Document Two'
404
+ d
405
+ end
406
+
407
+ let (:person1) do
408
+ p = DummyPerson.new
409
+ p.name = 'Alice'
410
+ p
411
+ end
412
+
413
+ let (:person2) do
414
+ p = DummyPerson.new
415
+ p.name = 'Bob'
416
+ p
417
+ end
418
+
419
+ let (:data) { <<END
420
+ _:1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/SomeClass> .
421
+ _:1 <http://purl.org/dc/terms/relation> _:2 .
422
+ _:2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Document> .
423
+ _:2 <http://purl.org/dc/terms/title> "Document One" .
424
+ _:2 <http://purl.org/dc/terms/creator> _:3 .
425
+ _:2 <http://purl.org/dc/terms/creator> _:4 .
426
+ _:4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
427
+ _:4 <http://xmlns.com/foaf/0.1/name> "Bob" .
428
+ _:3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
429
+ _:3 <http://xmlns.com/foaf/0.1/name> "Alice" .
430
+ _:3 <http://xmlns.com/foaf/0.1/knows> _:4 ."
431
+ END
432
+ }
433
+
434
+ after do
435
+ Object.send(:remove_const, "DummyDocument")
436
+ Object.send(:remove_const, "DummyPerson")
437
+ end
438
+
439
+ it 'should allow access to deep nodes' do
440
+ document1.creator = [person1, person2]
441
+ document2.creator = person1
442
+ person1.knows = person2
443
+ subject.item = [document1]
444
+ expect(subject.item.first.creator.first.knows.first.name).to eq ['Bob']
445
+ end
446
+ end
447
+ end