active-triples 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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