ladder 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/README.md +133 -110
- data/ladder.gemspec +6 -5
- data/lib/ladder/file.rb +15 -17
- data/lib/ladder/resource.rb +32 -22
- data/lib/ladder/resource/dynamic.rb +43 -49
- data/lib/ladder/resource/serializable.rb +54 -0
- data/lib/ladder/searchable.rb +5 -4
- data/lib/ladder/searchable/background.rb +43 -0
- data/lib/ladder/searchable/resource.rb +5 -64
- data/lib/ladder/version.rb +1 -1
- data/spec/ladder/file_spec.rb +53 -6
- data/spec/ladder/resource/dynamic_spec.rb +117 -115
- data/spec/ladder/resource_spec.rb +273 -8
- data/spec/ladder/searchable/background_spec.rb +112 -0
- data/spec/ladder/{file/searchable_spec.rb → searchable/file_spec.rb} +6 -26
- data/spec/ladder/searchable/resource_spec.rb +83 -0
- data/spec/shared/file.rb +8 -52
- data/spec/shared/resource.rb +54 -272
- data/spec/shared/searchable/file.rb +50 -0
- data/spec/shared/searchable/resource.rb +223 -0
- data/spec/spec_helper.rb +1 -0
- metadata +55 -33
- data/spec/ladder/resource/searchable_spec.rb +0 -221
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ladder::Searchable::Background do
|
4
|
+
before do
|
5
|
+
Mongoid.load!('mongoid.yml', :development)
|
6
|
+
Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
|
7
|
+
Mongoid.purge!
|
8
|
+
|
9
|
+
Elasticsearch::Model.client = Elasticsearch::Client.new host: 'localhost:9200', log: true
|
10
|
+
Elasticsearch::Model.client.indices.delete index: '_all'
|
11
|
+
|
12
|
+
LADDER_BASE_URI ||= 'http://example.org'
|
13
|
+
|
14
|
+
class Thing
|
15
|
+
include Ladder::Resource
|
16
|
+
include Ladder::Searchable::Background
|
17
|
+
end
|
18
|
+
|
19
|
+
class Datastream
|
20
|
+
include Ladder::File
|
21
|
+
include Ladder::Searchable::Background
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
Object.send(:remove_const, :LADDER_BASE_URI) if Object
|
27
|
+
Object.send(:remove_const, "Thing") if Object
|
28
|
+
Object.send(:remove_const, "Datastream") if Object
|
29
|
+
end
|
30
|
+
|
31
|
+
shared_context 'with data' do
|
32
|
+
before do
|
33
|
+
subject.class.configure type: RDF::DC.BibliographicResource
|
34
|
+
|
35
|
+
# non-localized literal
|
36
|
+
subject.class.field :alt
|
37
|
+
subject.class.property :alt, predicate: RDF::DC.alternative
|
38
|
+
subject.alt = 'Mumintrollet pa kometjakt'
|
39
|
+
|
40
|
+
# localized literal
|
41
|
+
subject.class.property :title, predicate: RDF::DC.title
|
42
|
+
subject.title = 'Comet in Moominland'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
shared_context 'with relations' do
|
47
|
+
before do
|
48
|
+
# related object
|
49
|
+
person.class.configure type: RDF::FOAF.Person
|
50
|
+
person.class.property :foaf_name, predicate: RDF::FOAF.name
|
51
|
+
person.foaf_name = 'Tove Jansson'
|
52
|
+
|
53
|
+
# many-to-many relation
|
54
|
+
person.class.property :things, predicate: RDF::DC.relation, class_name: 'Thing'
|
55
|
+
subject.class.property :people, predicate: RDF::DC.creator, class_name: 'Person'
|
56
|
+
subject.people << person
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with data' do
|
61
|
+
let(:subject) { Thing.new }
|
62
|
+
|
63
|
+
include_context 'with data'
|
64
|
+
|
65
|
+
it_behaves_like 'a Searchable'
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with relations' do
|
69
|
+
let(:subject) { Thing.new }
|
70
|
+
let(:person) { Person.new }
|
71
|
+
|
72
|
+
before do
|
73
|
+
class Person
|
74
|
+
include Ladder::Resource
|
75
|
+
include Ladder::Searchable::Background
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
after do
|
80
|
+
Object.send(:remove_const, "Person") if Object
|
81
|
+
end
|
82
|
+
|
83
|
+
include_context 'with data'
|
84
|
+
include_context 'with relations'
|
85
|
+
|
86
|
+
it_behaves_like 'a Searchable'
|
87
|
+
it_behaves_like 'a Searchable with related'
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with data from file' do
|
91
|
+
TEST_FILE ||= './spec/shared/moomin.pdf'
|
92
|
+
|
93
|
+
let(:subject) { Datastream.new file: open(TEST_FILE) }
|
94
|
+
let(:source) { open(TEST_FILE).read } # ASCII-8BIT (binary)
|
95
|
+
|
96
|
+
it_behaves_like 'a Searchable File'
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with data from string after creation' do
|
100
|
+
data = "And so Moomintroll was helplessly thrown out into a strange and dangerous world and dropped up to his ears in the first snowdrift of his experience. It felt unpleasantly prickly to his velvet skin, but at the same time his nose caught a new smell. It was a more serious smell than any he had met before, and slightly frightening. But it made him wide awake and greatly interested."
|
101
|
+
|
102
|
+
let(:subject) { Datastream.new }
|
103
|
+
let(:source) { data } # UTF-8 (string)
|
104
|
+
|
105
|
+
before do
|
106
|
+
subject.file = StringIO.new(source)
|
107
|
+
end
|
108
|
+
|
109
|
+
it_behaves_like 'a Searchable File'
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -9,7 +9,7 @@ describe Ladder::Searchable::File do
|
|
9
9
|
Elasticsearch::Model.client = Elasticsearch::Client.new host: 'localhost:9200', log: true
|
10
10
|
Elasticsearch::Model.client.indices.delete index: '_all'
|
11
11
|
|
12
|
-
LADDER_BASE_URI
|
12
|
+
LADDER_BASE_URI ||= 'http://example.org'
|
13
13
|
|
14
14
|
class Datastream
|
15
15
|
include Ladder::File
|
@@ -17,34 +17,18 @@ describe Ladder::Searchable::File do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
subject.save
|
23
|
-
Elasticsearch::Model.client.indices.flush
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should exist in the index' do
|
27
|
-
results = subject.class.search('Moomin*')
|
28
|
-
expect(results.count).to eq 1
|
29
|
-
expect(results.first.id).to eq subject.id.to_s
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'should contain full-text content' do
|
33
|
-
results = subject.class.search 'Moomin*', fields: '*'
|
34
|
-
expect(results.count).to eq 1
|
35
|
-
expect(results.first.fields.file.first).to include 'Moomin'
|
36
|
-
end
|
20
|
+
after do
|
21
|
+
Object.send(:remove_const, "Datastream") if Object
|
37
22
|
end
|
38
23
|
|
39
24
|
context 'with data from file' do
|
40
|
-
TEST_FILE
|
25
|
+
TEST_FILE ||= './spec/shared/moomin.pdf'
|
41
26
|
|
42
27
|
let(:subject) { Datastream.new file: open(TEST_FILE) }
|
43
28
|
let(:source) { open(TEST_FILE).read } # ASCII-8BIT (binary)
|
44
29
|
|
45
30
|
it_behaves_like 'a File'
|
46
|
-
|
47
|
-
include_context 'searchable'
|
31
|
+
it_behaves_like 'a Searchable File'
|
48
32
|
end
|
49
33
|
|
50
34
|
context 'with data from string after creation' do
|
@@ -58,11 +42,7 @@ describe Ladder::Searchable::File do
|
|
58
42
|
end
|
59
43
|
|
60
44
|
it_behaves_like 'a File'
|
61
|
-
|
62
|
-
include_context 'searchable'
|
45
|
+
it_behaves_like 'a Searchable File'
|
63
46
|
end
|
64
47
|
|
65
|
-
after do
|
66
|
-
Object.send(:remove_const, "Datastream") if Object
|
67
|
-
end
|
68
48
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ladder::Searchable::Resource do
|
4
|
+
before do
|
5
|
+
Mongoid.load!('mongoid.yml', :development)
|
6
|
+
Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
|
7
|
+
Mongoid.purge!
|
8
|
+
|
9
|
+
Elasticsearch::Model.client = Elasticsearch::Client.new host: 'localhost:9200', log: true
|
10
|
+
Elasticsearch::Model.client.indices.delete index: '_all'
|
11
|
+
|
12
|
+
LADDER_BASE_URI ||= 'http://example.org'
|
13
|
+
|
14
|
+
class Thing
|
15
|
+
include Ladder::Resource
|
16
|
+
include Ladder::Searchable
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
Object.send(:remove_const, :LADDER_BASE_URI) if Object
|
22
|
+
Object.send(:remove_const, "Thing") if Object
|
23
|
+
end
|
24
|
+
|
25
|
+
shared_context 'with data' do
|
26
|
+
before do
|
27
|
+
subject.class.configure type: RDF::DC.BibliographicResource
|
28
|
+
|
29
|
+
# non-localized literal
|
30
|
+
subject.class.field :alt
|
31
|
+
subject.class.property :alt, predicate: RDF::DC.alternative
|
32
|
+
subject.alt = 'Mumintrollet pa kometjakt'
|
33
|
+
|
34
|
+
# localized literal
|
35
|
+
subject.class.property :title, predicate: RDF::DC.title
|
36
|
+
subject.title = 'Comet in Moominland'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
shared_context 'with relations' do
|
41
|
+
before do
|
42
|
+
# related object
|
43
|
+
person.class.configure type: RDF::FOAF.Person
|
44
|
+
person.class.property :foaf_name, predicate: RDF::FOAF.name
|
45
|
+
person.foaf_name = 'Tove Jansson'
|
46
|
+
|
47
|
+
# many-to-many relation
|
48
|
+
person.class.property :things, predicate: RDF::DC.relation, class_name: 'Thing'
|
49
|
+
subject.class.property :people, predicate: RDF::DC.creator, class_name: 'Person'
|
50
|
+
subject.people << person
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with data' do
|
55
|
+
let(:subject) { Thing.new }
|
56
|
+
|
57
|
+
include_context 'with data'
|
58
|
+
|
59
|
+
it_behaves_like 'a Searchable'
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with relations' do
|
63
|
+
let(:subject) { Thing.new }
|
64
|
+
let(:person) { Person.new }
|
65
|
+
|
66
|
+
before do
|
67
|
+
class Person
|
68
|
+
include Ladder::Resource
|
69
|
+
include Ladder::Searchable
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
after do
|
74
|
+
Object.send(:remove_const, "Person") if Object
|
75
|
+
end
|
76
|
+
|
77
|
+
include_context 'with data'
|
78
|
+
include_context 'with relations'
|
79
|
+
|
80
|
+
it_behaves_like 'a Searchable with related'
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/spec/shared/file.rb
CHANGED
@@ -2,28 +2,6 @@ require 'mimemagic'
|
|
2
2
|
|
3
3
|
shared_examples 'a File' do
|
4
4
|
|
5
|
-
shared_context 'with relations' do
|
6
|
-
let(:thing) { Thing.new }
|
7
|
-
|
8
|
-
before do
|
9
|
-
class Thing
|
10
|
-
include Ladder::Resource
|
11
|
-
end
|
12
|
-
|
13
|
-
# implicit from #property
|
14
|
-
thing.class.property :files, :predicate => RDF::DC.relation, :class_name => subject.class.name, :inverse_of => nil
|
15
|
-
thing.files << subject
|
16
|
-
|
17
|
-
# TODO: build some relations of various types
|
18
|
-
# explicit using HABTM
|
19
|
-
# explicit has-one
|
20
|
-
end
|
21
|
-
|
22
|
-
after do
|
23
|
-
Object.send(:remove_const, 'Thing')
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
5
|
describe 'LADDER_BASE_URI' do
|
28
6
|
it 'should automatically have a base URI' do
|
29
7
|
expect(subject.rdf_subject.parent).to eq RDF::URI('http://example.org/datastreams/')
|
@@ -43,22 +21,22 @@ shared_examples 'a File' do
|
|
43
21
|
end
|
44
22
|
|
45
23
|
describe '#save' do
|
46
|
-
|
47
|
-
|
24
|
+
before do
|
25
|
+
subject.save
|
48
26
|
end
|
49
|
-
end
|
50
27
|
|
51
|
-
describe '#find' do
|
52
28
|
it 'should be retrievable' do
|
53
|
-
subject.save
|
54
29
|
found = subject.class.find(subject.id)
|
55
|
-
|
56
30
|
expect(found).to eq subject
|
57
31
|
expect(found.data).to eq subject.data
|
58
32
|
expect(found.data).to eq source.force_encoding(found.data.encoding)
|
59
33
|
end
|
60
34
|
end
|
61
35
|
|
36
|
+
describe '#grid' do
|
37
|
+
# TODO
|
38
|
+
end
|
39
|
+
|
62
40
|
describe '#attributes' do
|
63
41
|
before do
|
64
42
|
subject.save
|
@@ -84,31 +62,9 @@ shared_examples 'a File' do
|
|
84
62
|
expect(subject.resource).to eq subject.update_resource
|
85
63
|
end
|
86
64
|
|
87
|
-
it 'should not have
|
88
|
-
expect(subject.
|
65
|
+
it 'should not have any statements' do
|
66
|
+
expect(subject.update_resource.statements).to be_empty
|
89
67
|
end
|
90
68
|
end
|
91
69
|
|
92
|
-
context 'with one-sided has-many' do
|
93
|
-
include_context 'with relations'
|
94
|
-
|
95
|
-
it 'should have a relation' do
|
96
|
-
expect(thing.relations['files'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
|
97
|
-
expect(thing.files.to_a).to include subject
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'should not have an inverse relation' do
|
101
|
-
expect(thing.relations['files'].inverse_of).to be nil
|
102
|
-
expect(subject.relations).to be_empty
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should have a valid predicate' do
|
106
|
-
expect(thing.class.properties['files'].predicate).to eq RDF::DC.relation
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'should not have an inverse predicate' do
|
110
|
-
expect(subject.class.properties).to be_empty
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
70
|
end
|
data/spec/shared/resource.rb
CHANGED
@@ -1,72 +1,4 @@
|
|
1
1
|
shared_examples 'a Resource' do
|
2
|
-
let(:subject) { Thing.new }
|
3
|
-
let(:person) { Person.new }
|
4
|
-
|
5
|
-
shared_context 'with data' do
|
6
|
-
before do
|
7
|
-
# non-localized literal
|
8
|
-
subject.class.field :alt
|
9
|
-
subject.class.property :alt, :predicate => RDF::DC.alternative
|
10
|
-
subject.alt = 'Mumintrollet pa kometjakt'
|
11
|
-
|
12
|
-
# localized literal
|
13
|
-
subject.class.property :title, :predicate => RDF::DC.title
|
14
|
-
subject.title = 'Comet in Moominland'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
shared_context 'with relations' do
|
19
|
-
let(:concept) { Concept.new }
|
20
|
-
let(:part) { Part.new }
|
21
|
-
|
22
|
-
include_context 'with data'
|
23
|
-
|
24
|
-
before do
|
25
|
-
class Concept
|
26
|
-
include Ladder::Resource
|
27
|
-
end
|
28
|
-
|
29
|
-
class Part
|
30
|
-
include Ladder::Resource
|
31
|
-
end
|
32
|
-
|
33
|
-
# many-to-many
|
34
|
-
person.class.property :things, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
35
|
-
subject.class.property :people, :predicate => RDF::DC.creator, :class_name => 'Person'
|
36
|
-
subject.people << person
|
37
|
-
|
38
|
-
# one-sided has-many
|
39
|
-
subject.class.has_and_belongs_to_many :concepts, inverse_of: nil
|
40
|
-
subject.class.property :concepts, :predicate => RDF::DC.subject, :class_name => 'Concept'
|
41
|
-
subject.concepts << concept
|
42
|
-
|
43
|
-
# embedded one
|
44
|
-
part.class.embedded_in :thing
|
45
|
-
part.class.property :thing, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
46
|
-
subject.class.embeds_one :part, cascade_callbacks: true
|
47
|
-
subject.class.property :part, :predicate => RDF::DC.hasPart, :class_name => 'Part'
|
48
|
-
subject.part = part
|
49
|
-
subject.save
|
50
|
-
end
|
51
|
-
|
52
|
-
after do
|
53
|
-
Object.send(:remove_const, 'Concept')
|
54
|
-
Object.send(:remove_const, 'Part')
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should have relations' do
|
58
|
-
expect(subject.title).to eq 'Comet in Moominland'
|
59
|
-
expect(subject.people.to_a).to include person
|
60
|
-
expect(subject.concepts.to_a).to include concept
|
61
|
-
expect(subject.part).to eq part
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should have inverse relations' do
|
65
|
-
expect(person.things.to_a).to include subject
|
66
|
-
expect(concept.relations).to be_empty
|
67
|
-
expect(part.thing).to eq subject
|
68
|
-
end
|
69
|
-
end
|
70
2
|
|
71
3
|
describe 'LADDER_BASE_URI' do
|
72
4
|
it 'should automatically have a base URI' do
|
@@ -76,8 +8,6 @@ shared_examples 'a Resource' do
|
|
76
8
|
|
77
9
|
describe '#property' do
|
78
10
|
context 'with non-localized literal' do
|
79
|
-
include_context 'with data'
|
80
|
-
|
81
11
|
it 'should return non-localized value' do
|
82
12
|
expect(subject.alt).to eq 'Mumintrollet pa kometjakt'
|
83
13
|
end
|
@@ -91,14 +21,12 @@ shared_examples 'a Resource' do
|
|
91
21
|
end
|
92
22
|
|
93
23
|
it 'allows resetting of properties' do
|
94
|
-
subject.class.property :alt, :
|
24
|
+
subject.class.property :alt, predicate: RDF::DC.title
|
95
25
|
expect(subject.class.properties['alt'].predicate).to eq RDF::DC.title
|
96
26
|
end
|
97
27
|
end
|
98
28
|
|
99
29
|
context 'with localized literal' do
|
100
|
-
include_context 'with data'
|
101
|
-
|
102
30
|
it 'should return localized value' do
|
103
31
|
expect(subject.title).to eq 'Comet in Moominland'
|
104
32
|
end
|
@@ -112,241 +40,95 @@ shared_examples 'a Resource' do
|
|
112
40
|
end
|
113
41
|
|
114
42
|
it 'allows resetting of properties' do
|
115
|
-
subject.class.property :title, :
|
43
|
+
subject.class.property :title, predicate: RDF::DC.alternative
|
116
44
|
expect(subject.class.properties['title'].predicate).to eq RDF::DC.alternative
|
117
45
|
end
|
118
46
|
end
|
47
|
+
end
|
119
48
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
it 'should have a relation' do
|
124
|
-
expect(subject.relations['people'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
|
125
|
-
expect(subject.people.to_a).to include person
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'should have an inverse relation' do
|
129
|
-
expect(person.relations['things'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
|
130
|
-
expect(person.things.to_a).to include subject
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'should have a valid predicate' do
|
134
|
-
expect(subject.class.properties['people'].predicate).to eq RDF::DC.creator
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'should have a valid inverse predicate' do
|
138
|
-
expect(person.class.properties['things'].predicate).to eq RDF::DC.relation
|
139
|
-
end
|
49
|
+
describe '#update_resource' do
|
50
|
+
before do
|
51
|
+
subject.update_resource
|
140
52
|
end
|
141
53
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
it 'should have a relation' do
|
146
|
-
expect(subject.relations['concepts'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
|
147
|
-
expect(subject.concepts.to_a).to include concept
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'should not have an inverse relation' do
|
151
|
-
expect(subject.relations['concepts'].inverse_of).to be nil
|
152
|
-
expect(concept.relations).to be_empty
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'should have a valid predicate' do
|
156
|
-
expect(subject.class.properties['concepts'].predicate).to eq RDF::DC.subject
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'should not have an inverse predicate' do
|
160
|
-
expect(concept.class.properties).to be_empty
|
54
|
+
it 'should have a non-localized literal object' do
|
55
|
+
subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.title).each_statement do |s|
|
56
|
+
expect(s.object.to_s).to eq 'Comet in Moominland'
|
161
57
|
end
|
162
58
|
end
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
subject.class.property :people, :predicate => RDF::DC.creator, :class_name => 'Person'
|
168
|
-
|
169
|
-
person.class.embedded_in :thing
|
170
|
-
person.class.property :thing, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
171
|
-
|
172
|
-
subject.people << person
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'should have a relation' do
|
176
|
-
expect(subject.relations['people'].relation).to eq (Mongoid::Relations::Embedded::Many)
|
177
|
-
expect(subject.people.to_a).to include person
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'should have an inverse relation' do
|
181
|
-
expect(person.relations['thing'].relation).to eq (Mongoid::Relations::Embedded::In)
|
182
|
-
expect(person.thing).to eq subject
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'should have a valid predicate' do
|
186
|
-
expect(subject.class.properties['people'].predicate).to eq RDF::DC.creator
|
59
|
+
|
60
|
+
it 'should have a localized literal object' do
|
61
|
+
subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.alternative).each_statement do |s|
|
62
|
+
expect(s.object.to_s).to eq 'Mumintrollet pa kometjakt'
|
187
63
|
end
|
64
|
+
end
|
188
65
|
|
189
|
-
|
190
|
-
|
191
|
-
end
|
66
|
+
it 'should not have related objects' do
|
67
|
+
expect(subject.resource.query(object: subject)).to be_empty
|
192
68
|
end
|
193
69
|
end
|
194
70
|
|
195
|
-
describe '
|
196
|
-
context '
|
197
|
-
include_context 'with relations'
|
198
|
-
|
71
|
+
describe '#<<' do
|
72
|
+
context 'with defined field' do
|
199
73
|
before do
|
200
|
-
subject.
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'should have a literal object' do
|
204
|
-
subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.title).each_statement do |s|
|
205
|
-
expect(s.object.to_s).to eq 'Comet in Moominland'
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
it 'should have an embedded object' do
|
210
|
-
query = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.hasPart)
|
211
|
-
expect(query.count).to eq 1
|
212
|
-
|
213
|
-
query.each_statement do |s|
|
214
|
-
expect(s.object).to eq part.rdf_subject
|
215
|
-
end
|
74
|
+
subject << RDF::Statement(nil, RDF::DC.title, 'Kometen kommer')
|
216
75
|
end
|
217
|
-
|
218
|
-
it 'should
|
219
|
-
|
220
|
-
expect(query.count).to eq 1
|
221
|
-
expect(query.to_hash).to eq part.resource.statements.to_hash
|
222
|
-
|
223
|
-
query.each_statement do |s|
|
224
|
-
expect(s.object).to eq subject.rdf_subject
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'should not have related objects' do
|
229
|
-
expect(subject.resource.query(:subject => person.rdf_subject)).to be_empty
|
230
|
-
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'should not have related object relations' do
|
234
|
-
expect(person.resource.statements).to be_empty
|
235
|
-
expect(concept.resource.statements).to be_empty
|
76
|
+
|
77
|
+
it 'should update existing values' do
|
78
|
+
expect(subject.title).to eq 'Kometen kommer'
|
236
79
|
end
|
237
80
|
end
|
238
81
|
|
239
|
-
context 'with
|
240
|
-
include_context 'with relations'
|
241
|
-
|
82
|
+
context 'with undefined field' do
|
242
83
|
before do
|
243
|
-
subject
|
84
|
+
subject << RDF::Statement(nil, RDF::DC.description, "Second in Tove Jansson's series of Moomin books")
|
244
85
|
end
|
245
86
|
|
246
|
-
it 'should
|
247
|
-
|
248
|
-
|
249
|
-
end
|
87
|
+
it 'should ignore undefined properties' do
|
88
|
+
expect(subject.fields['description']).to be_nil
|
89
|
+
expect(subject.resource.query(predicate: RDF::DC.description)).to be_empty
|
250
90
|
end
|
91
|
+
end
|
251
92
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
query.each_statement do |s|
|
257
|
-
expect(s.object).to eq part.rdf_subject
|
258
|
-
end
|
93
|
+
context 'with a URI value' do
|
94
|
+
before do
|
95
|
+
subject.class.property :identifier, predicate: RDF::DC.identifier
|
96
|
+
subject << RDF::Statement(nil, RDF::DC.identifier, RDF::URI('http://some.uri'))
|
259
97
|
end
|
260
|
-
|
261
|
-
it 'should
|
262
|
-
|
263
|
-
expect(query.count).to eq 1
|
264
|
-
expect(query.to_hash).to eq part.resource.statements.to_hash
|
265
|
-
|
266
|
-
query.each_statement do |s|
|
267
|
-
expect(s.object).to eq subject.rdf_subject
|
268
|
-
end
|
98
|
+
|
99
|
+
it 'should store the URI as a string' do
|
100
|
+
expect(subject.identifier).to eq 'http://some.uri'
|
269
101
|
end
|
270
102
|
|
271
|
-
it 'should
|
272
|
-
|
273
|
-
|
274
|
-
expect(
|
275
|
-
|
276
|
-
query_creator.each_statement do |s|
|
277
|
-
expect(s.object).to eq person.rdf_subject
|
278
|
-
end
|
279
|
-
|
280
|
-
# one-sided has-many
|
281
|
-
query_subject = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.subject)
|
282
|
-
expect(query_subject.count).to eq 1
|
283
|
-
|
284
|
-
query_subject.each_statement do |s|
|
285
|
-
expect(s.object).to eq concept.rdf_subject
|
286
|
-
end
|
103
|
+
it 'should cast a URI into the resource' do
|
104
|
+
subject.update_resource
|
105
|
+
query = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.identifier)
|
106
|
+
expect(query.first_object).to be_a_kind_of RDF::URI
|
287
107
|
end
|
108
|
+
end
|
109
|
+
end
|
288
110
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
expect(query.count).to eq 1
|
293
|
-
expect(query.to_hash).to eq person.resource.statements.to_hash
|
294
|
-
|
295
|
-
query.each_statement do |s|
|
296
|
-
expect(s.object).to eq subject.rdf_subject
|
297
|
-
end
|
298
|
-
|
299
|
-
# one-sided has-many
|
300
|
-
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
301
|
-
expect(concept.resource.statements).to be_empty
|
302
|
-
end
|
111
|
+
describe '#rdf_label' do
|
112
|
+
it 'should return the default label' do
|
113
|
+
expect(subject.rdf_label.to_a).to eq ['Comet in Moominland']
|
303
114
|
end
|
115
|
+
end
|
304
116
|
|
305
|
-
|
306
|
-
include_context 'with relations'
|
307
|
-
|
308
|
-
before do
|
309
|
-
subject.update_resource(:related => true)
|
310
|
-
subject.update_resource
|
311
|
-
end
|
117
|
+
context 'a serializable' do
|
312
118
|
|
313
|
-
|
314
|
-
|
315
|
-
|
119
|
+
describe '#as_jsonld' do
|
120
|
+
it 'should output a valid jsonld representation of itself' do
|
121
|
+
graph = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld)
|
122
|
+
expect(subject.update_resource.to_hash).to eq graph.to_hash
|
316
123
|
end
|
124
|
+
end
|
317
125
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
expect(query.count).to eq 1
|
322
|
-
expect(query.to_hash).to eq person.resource.statements.to_hash
|
323
|
-
|
324
|
-
query.each_statement do |s|
|
325
|
-
expect(s.object).to eq subject.rdf_subject
|
326
|
-
end
|
327
|
-
|
328
|
-
# one-sided has-many
|
329
|
-
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
330
|
-
expect(concept.resource.statements).to be_empty
|
126
|
+
describe '#as_qname' do
|
127
|
+
it 'should output a valid qname representation of itself' do
|
128
|
+
# TODO
|
331
129
|
end
|
332
130
|
end
|
333
|
-
end
|
334
|
-
|
335
|
-
describe '#as_jsonld' do
|
336
|
-
include_context 'with relations'
|
337
|
-
|
338
|
-
it 'should output a valid jsonld representation of itself' do
|
339
|
-
g = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld)
|
340
|
-
expect(subject.resource.to_hash == g.to_hash).to be true
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
describe '#rdf_label' do
|
345
|
-
include_context 'with data'
|
346
131
|
|
347
|
-
it 'should return the default label' do
|
348
|
-
expect(subject.rdf_label.to_a).to eq ['Comet in Moominland']
|
349
|
-
end
|
350
132
|
end
|
351
133
|
|
352
134
|
end
|