ladder 0.2.1 → 0.3.0

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.
@@ -6,170 +6,172 @@ describe Ladder::Resource::Dynamic do
6
6
  Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
7
7
  Mongoid.purge!
8
8
 
9
- LADDER_BASE_URI = 'http://example.org'
9
+ LADDER_BASE_URI ||= 'http://example.org'
10
10
 
11
11
  class Thing
12
12
  include Ladder::Resource::Dynamic
13
13
  end
14
-
15
- class Person
16
- include Ladder::Resource::Dynamic
17
- end
18
14
  end
19
15
 
20
- it_behaves_like 'a Resource'
16
+ after do
17
+ Object.send(:remove_const, :LADDER_BASE_URI) if Object
18
+ Object.send(:remove_const, "Thing") if Object
19
+ end
21
20
 
22
- shared_context 'with data' do
21
+ context 'with data' do
23
22
  let(:subject) { Thing.new }
24
23
 
25
24
  before do
26
25
  # non-localized literal
27
26
  subject.class.field :alt
28
- subject.class.property :alt, :predicate => RDF::DC.alternative
27
+ subject.class.property :alt, predicate: RDF::DC.alternative
29
28
  subject.alt = 'Mumintrollet pa kometjakt'
30
29
 
31
30
  # localized literal
32
- subject.class.property :title, :predicate => RDF::DC.title
31
+ subject.class.property :title, predicate: RDF::DC.title
33
32
  subject.title = 'Comet in Moominland'
34
33
  end
35
- end
36
-
37
- describe '#property' do
38
- include_context 'with data'
39
34
 
40
- context 'with undefined property' do
41
- before do
42
- subject.property :description, :predicate => RDF::DC.description
43
- subject.description = "Second in Tove Jansson's series of Moomin books"
35
+ it_behaves_like 'a Resource'
36
+
37
+ describe '#property' do
38
+ context 'with undefined property' do
39
+ before do
40
+ subject.property :description, predicate: RDF::DC.description
41
+ subject.description = "Second in Tove Jansson's series of Moomin books"
42
+ end
43
+
44
+ it 'should create a context' do
45
+ expect(subject._context).to eq({description: RDF::DC.description.to_uri.to_s})
46
+ end
47
+
48
+ it 'should build an accessor' do
49
+ expect(subject.description).to eq "Second in Tove Jansson's series of Moomin books"
50
+ end
44
51
  end
45
52
 
46
- it 'should create a context' do
47
- expect(subject._context).to eq({:description => RDF::DC.description.to_uri.to_s})
48
- end
53
+ context 'with conflicting property' do
54
+ before do
55
+ subject.property :title, predicate: RDF::DC11.title
56
+ subject.dc11_title = "Kometjakten"
57
+ end
58
+
59
+ it 'should create a context' do
60
+ expect(subject._context).to eq({dc11_title: RDF::DC11.title.to_uri.to_s})
61
+ end
49
62
 
50
- it 'should build an accessor' do
51
- expect(subject.description).to eq "Second in Tove Jansson's series of Moomin books"
63
+ it 'should build an accessor' do
64
+ expect(subject.dc11_title).to eq "Kometjakten"
65
+ end
52
66
  end
53
67
  end
54
-
55
- context 'with conflicting property' do
68
+
69
+ describe '#update_resource' do
56
70
  before do
57
- subject.property :title, :predicate => RDF::DC11.title
71
+ # undefined property
72
+ subject.property :description, predicate: RDF::DC.description
73
+ subject.description = "Second in Tove Jansson's series of Moomin books"
74
+
75
+ # conflicting property
76
+ subject.property :title, predicate: RDF::DC11.title
58
77
  subject.dc11_title = "Kometjakten"
59
- end
60
78
 
61
- it 'should create a context' do
62
- expect(subject._context).to eq({:dc11_title => RDF::DC11.title.to_uri.to_s})
79
+ # defined field
80
+ subject << RDF::Statement(nil, RDF::DC.title, 'Kometen kommer')
81
+
82
+ # conflicting property
83
+ subject << RDF::Statement(nil, RDF::DC.alternative, "Kometjakten")
84
+
85
+ # URI value
86
+ subject << RDF::Statement(nil, RDF::DC.identifier, RDF::URI('http://some.uri'))
87
+
88
+ subject.update_resource
63
89
  end
64
-
65
- it 'should build an accessor' do
66
- expect(subject.dc11_title).to eq "Kometjakten"
90
+
91
+ it 'should have updated values' do
92
+ expect(subject.resource.statements.count).to eq 5
93
+ expect(subject.resource.query(predicate: RDF::DC.description, object: "Second in Tove Jansson's series of Moomin books").count).to eq 1
94
+ expect(subject.resource.query(predicate: RDF::DC11.title, object: "Kometjakten").count).to eq 1
95
+ expect(subject.resource.query(predicate: RDF::DC.title, object: RDF::Literal.new('Kometen kommer', language: :en)).count).to eq 1
96
+ expect(subject.resource.query(predicate: RDF::DC.alternative, object: "Kometjakten").count).to eq 1
97
+ expect(subject.resource.query(predicate: RDF::DC.identifier, object: RDF::URI('http://some.uri')).count).to eq 1
67
98
  end
68
99
  end
69
- end
70
-
71
- describe '#<<' do
72
- include_context 'with data'
73
100
 
74
- context 'with defined field' do
75
- before do
76
- subject << RDF::Statement(nil, RDF::DC.title, 'Kometen kommer')
77
- end
101
+ describe '#<<' do
102
+ context 'with defined field' do
103
+ before do
104
+ subject << RDF::Statement(nil, RDF::DC.title, 'Kometen kommer')
105
+ end
78
106
 
79
- it 'should not create a context' do
80
- expect(subject._context).to be nil
81
- end
107
+ it 'should not create a context' do
108
+ expect(subject._context).to be nil
109
+ end
82
110
 
83
- it 'should update existing values' do
84
- expect(subject.title).to eq 'Kometen kommer'
111
+ it 'should update existing values' do
112
+ expect(subject.title).to eq 'Kometen kommer'
113
+ end
85
114
  end
86
- end
87
115
 
88
- context 'with undefined field' do
89
- before do
90
- subject << RDF::Statement(nil, RDF::DC.description, "Second in Tove Jansson's series of Moomin books")
91
- end
116
+ context 'with undefined field' do
117
+ before do
118
+ subject << RDF::Statement(nil, RDF::DC.description, "Second in Tove Jansson's series of Moomin books")
119
+ end
92
120
 
93
- it 'should create a context' do
94
- expect(subject._context).to eq({:description => RDF::DC.description.to_uri.to_s})
95
- end
121
+ it 'should create a context' do
122
+ expect(subject._context).to eq({ description: RDF::DC.description.to_uri.to_s })
123
+ end
96
124
 
97
- it 'should build an accessor' do
98
- expect(subject.description).to eq "Second in Tove Jansson's series of Moomin books"
125
+ it 'should build an accessor' do
126
+ expect(subject.description).to eq "Second in Tove Jansson's series of Moomin books"
127
+ end
99
128
  end
100
- end
101
129
 
102
- context 'with conflicting field' do
103
- before do
104
- subject << RDF::Statement(nil, RDF::DC11.title, "Kometjakten")
105
- end
130
+ context 'with conflicting property' do
131
+ before do
132
+ subject << RDF::Statement(nil, RDF::DC11.title, "Kometjakten")
133
+ end
106
134
 
107
- it 'should create a context' do
108
- expect(subject._context).to eq({:dc11_title => RDF::DC11.title.to_uri.to_s})
109
- end
135
+ it 'should create a context' do
136
+ expect(subject._context).to eq({ dc11_title: RDF::DC11.title.to_uri.to_s })
137
+ end
110
138
 
111
- it 'should build an accessor' do
112
- expect(subject.dc11_title).to eq "Kometjakten"
139
+ it 'should build an accessor' do
140
+ expect(subject.dc11_title).to eq "Kometjakten"
141
+ end
113
142
  end
114
- end
115
143
 
144
+ context 'with a URI value' do
145
+ before do
146
+ subject << RDF::Statement(nil, RDF::DC.identifier, RDF::URI('http://some.uri'))
147
+ end
148
+
149
+ it 'should store the URI as a string' do
150
+ expect(subject.identifier).to eq 'http://some.uri'
151
+ end
116
152
 
117
- context 'with a URI value' do
153
+ it 'should cast a URI into the resource' do
154
+ subject.update_resource
155
+ query = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.identifier)
156
+ expect(query.first_object).to be_a_kind_of RDF::URI
157
+ end
158
+ end
159
+ end
160
+
161
+ describe '#resource_class' do
118
162
  before do
119
- subject << RDF::Statement(nil, RDF::DC.identifier, RDF::URI('http://some.uri'))
120
- subject.update_resource
163
+ subject.property :description, predicate: RDF::DC.description
121
164
  end
122
-
123
- it 'should store the URI as a string' do
124
- expect(subject.identifier).to eq 'http://some.uri'
165
+
166
+ it 'should have modified properties on the instance' do
167
+ expect(subject.resource.class.properties.keys).to include 'description'
125
168
  end
126
169
 
127
- it 'should cast a URI into the resource' do
128
- query = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.identifier)
129
- expect(query.count).to eq 1
130
- expect(query.first_object).to be_a_kind_of RDF::URI
170
+ it 'should not modify the global class properties' do
171
+ expect(subject.class.resource_class.properties.keys).to_not include 'description'
172
+ expect(subject.class.resource_class.properties).to eq subject.class.new.class.resource_class.properties
131
173
  end
132
174
  end
133
-
134
175
  end
135
-
136
- describe '#update_resource' do
137
- include_context 'with data'
138
-
139
- before do
140
- # undefined property
141
- subject.property :description, :predicate => RDF::DC.description
142
- subject.description = "Second in Tove Jansson's series of Moomin books"
143
-
144
- # conflicting property
145
- subject.property :title, :predicate => RDF::DC11.title
146
- subject.dc11_title = "Kometjakten"
147
176
 
148
- # defined field
149
- subject << RDF::Statement(nil, RDF::DC.title, 'Kometen kommer')
150
-
151
- # conflicting field
152
- subject << RDF::Statement(nil, RDF::DC.alternative, "Kometjakten")
153
-
154
- # URI value
155
- subject << RDF::Statement(nil, RDF::DC.identifier, RDF::URI('http://some.uri'))
156
-
157
- subject.update_resource
158
- end
159
-
160
- it 'should have updated values' do
161
- expect(subject.resource.statements.count).to eq 5
162
- expect(subject.resource.query(:predicate => RDF::DC.description, :object => "Second in Tove Jansson's series of Moomin books").count).to eq 1
163
- expect(subject.resource.query(:predicate => RDF::DC11.title, :object => "Kometjakten").count).to eq 1
164
- expect(subject.resource.query(:predicate => RDF::DC.title, :object => RDF::Literal.new('Kometen kommer', :language => :en)).count).to eq 1
165
- expect(subject.resource.query(:predicate => RDF::DC.alternative, :object => "Kometjakten").count).to eq 1
166
- expect(subject.resource.query(:predicate => RDF::DC.identifier, :object => RDF::URI('http://some.uri')).count).to eq 1
167
- end
168
- end
169
-
170
- after do
171
- Object.send(:remove_const, :LADDER_BASE_URI) if Object
172
- Object.send(:remove_const, "Thing") if Object
173
- Object.send(:remove_const, "Person") if Object
174
- end
175
177
  end
@@ -6,22 +6,287 @@ describe Ladder::Resource do
6
6
  Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
7
7
  Mongoid.purge!
8
8
 
9
- LADDER_BASE_URI = 'http://example.org'
9
+ LADDER_BASE_URI ||= 'http://example.org'
10
10
 
11
11
  class Thing
12
12
  include Ladder::Resource
13
13
  end
14
-
15
- class Person
16
- include Ladder::Resource
17
- end
18
14
  end
19
15
 
20
- it_behaves_like 'a Resource'
21
-
22
16
  after do
23
17
  Object.send(:remove_const, :LADDER_BASE_URI) if Object
24
18
  Object.send(:remove_const, "Thing") if Object
25
- Object.send(:remove_const, "Person") if Object
26
19
  end
20
+
21
+ shared_context 'with data' do
22
+ before do
23
+ subject.class.configure type: RDF::DC.BibliographicResource
24
+
25
+ # non-localized literal
26
+ subject.class.field :alt
27
+ subject.class.property :alt, predicate: RDF::DC.alternative
28
+ subject.alt = 'Mumintrollet pa kometjakt'
29
+
30
+ # localized literal
31
+ subject.class.property :title, predicate: RDF::DC.title
32
+ subject.title = 'Comet in Moominland'
33
+ end
34
+ end
35
+
36
+ shared_context 'with relations' do
37
+ let(:person) { Person.new }
38
+ let(:concept) { Concept.new }
39
+ let(:part) { Part.new }
40
+
41
+ before do
42
+ class Person
43
+ include Ladder::Resource
44
+ end
45
+
46
+ class Concept
47
+ include Ladder::Resource
48
+ end
49
+
50
+ class Part
51
+ include Ladder::Resource
52
+ end
53
+
54
+ person.class.configure type: RDF::DC.AgentClass
55
+ concept.class.configure type: RDF::SKOS.Concept
56
+ part.class.configure type: RDF::DC.PhysicalResource
57
+
58
+ # many-to-many
59
+ person.class.property :things, predicate: RDF::DC.relation, class_name: 'Thing'
60
+ subject.class.property :people, predicate: RDF::DC.creator, class_name: 'Person'
61
+ subject.people << person
62
+
63
+ # one-sided has-many
64
+ subject.class.has_and_belongs_to_many :concepts, inverse_of: nil
65
+ subject.class.property :concepts, predicate: RDF::DC.subject, class_name: 'Concept'
66
+ subject.concepts << concept
67
+
68
+ # embedded one
69
+ part.class.embedded_in :thing
70
+ part.class.property :thing, predicate: RDF::DC.relation, class_name: 'Thing'
71
+ subject.class.embeds_one :part, cascade_callbacks: true
72
+ subject.class.property :part, predicate: RDF::DC.hasPart, class_name: 'Part'
73
+ subject.part = part
74
+ subject.save
75
+ end
76
+
77
+ after do
78
+ Object.send(:remove_const, "Person") if Object
79
+ Object.send(:remove_const, 'Concept') if Object
80
+ Object.send(:remove_const, 'Part') if Object
81
+ end
82
+
83
+ it 'should have relations' do
84
+ expect(subject.people.to_a).to include person
85
+ expect(subject.concepts.to_a).to include concept
86
+ expect(subject.part).to eq part
87
+ end
88
+
89
+ it 'should have inverse relations' do
90
+ expect(person.things.to_a).to include subject
91
+ expect(concept.relations).to be_empty
92
+ expect(part.thing).to eq subject
93
+ end
94
+
95
+ context 'with many-to-many' do
96
+ it 'should have a relation' do
97
+ expect(subject.relations['people'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
98
+ expect(subject.people.to_a).to include person
99
+ end
100
+
101
+ it 'should have an inverse relation' do
102
+ expect(person.relations['things'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
103
+ expect(person.things.to_a).to include subject
104
+ end
105
+
106
+ it 'should have a valid predicate' do
107
+ expect(subject.class.properties['people'].predicate).to eq RDF::DC.creator
108
+ end
109
+
110
+ it 'should have a valid inverse predicate' do
111
+ expect(person.class.properties['things'].predicate).to eq RDF::DC.relation
112
+ end
113
+ end
114
+
115
+ context 'with one-sided has-many' do
116
+ it 'should have a relation' do
117
+ expect(subject.relations['concepts'].relation).to eq (Mongoid::Relations::Referenced::ManyToMany)
118
+ expect(subject.concepts.to_a).to include concept
119
+ end
120
+
121
+ it 'should not have an inverse relation' do
122
+ expect(subject.relations['concepts'].inverse_of).to be nil
123
+ expect(concept.relations).to be_empty
124
+ end
125
+
126
+ it 'should have a valid predicate' do
127
+ expect(subject.class.properties['concepts'].predicate).to eq RDF::DC.subject
128
+ end
129
+
130
+ it 'should not have an inverse predicate' do
131
+ expect(concept.class.properties).to be_empty
132
+ end
133
+ end
134
+
135
+ context 'with embedded-one' do
136
+ it 'should have a relation' do
137
+ expect(subject.relations['part'].relation).to eq (Mongoid::Relations::Embedded::One)
138
+ expect(subject.part).to eq part
139
+ end
140
+
141
+ it 'should have an inverse relation' do
142
+ expect(part.relations['thing'].relation).to eq (Mongoid::Relations::Embedded::In)
143
+ expect(part.thing).to eq subject
144
+ end
145
+
146
+ it 'should have a valid predicate' do
147
+ expect(subject.class.properties['part'].predicate).to eq RDF::DC.hasPart
148
+ end
149
+
150
+ it 'should have a valid inverse predicate' do
151
+ expect(part.class.properties['thing'].predicate).to eq RDF::DC.relation
152
+ end
153
+ end
154
+
155
+ context '#update_resource with related' do
156
+ # TODO add tests for autosaved relations
157
+ before do
158
+ subject.update_resource(related: true)
159
+ end
160
+
161
+ it 'should have a literal object' do
162
+ query = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.title)
163
+ expect(query.first_object.to_s).to eq 'Comet in Moominland'
164
+ end
165
+
166
+ it 'should have an embedded object' do
167
+ query = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.hasPart)
168
+ expect(query.count).to eq 1
169
+ expect(query.first_object).to eq part.rdf_subject
170
+ end
171
+
172
+ it 'should have an embedded object relation' do
173
+ query = subject.resource.query(subject: part.rdf_subject, predicate: RDF::DC.relation)
174
+ expect(query.count).to eq 1
175
+ expect(query.first_object).to eq subject.rdf_subject
176
+ end
177
+
178
+ it 'should have related objects' do
179
+ # many-to-many
180
+ query_creator = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.creator)
181
+ expect(query_creator.count).to eq 1
182
+ expect(query_creator.first_object).to eq person.rdf_subject
183
+
184
+ # one-sided has-many
185
+ query_subject = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.subject)
186
+ expect(query_subject.count).to eq 1
187
+ expect(query_subject.first_object).to eq concept.rdf_subject
188
+
189
+ # embedded-one
190
+ query_part = subject.resource.query(subject: subject.rdf_subject, predicate: RDF::DC.hasPart)
191
+ expect(query_part.count).to eq 1
192
+ expect(query_part.first_object).to eq part.rdf_subject
193
+ end
194
+
195
+ it 'should have related object relations' do
196
+ # many-to-many
197
+ query = person.resource.query(subject: person.rdf_subject, predicate: RDF::DC.relation)
198
+ expect(query.count).to eq 1
199
+ expect(query.first_object).to eq subject.rdf_subject
200
+
201
+ # one-sided has-many
202
+ expect(concept.resource.query(object: subject.rdf_subject)).to be_empty
203
+
204
+ # embedded-one
205
+ query = part.resource.query(subject: part.rdf_subject, predicate: RDF::DC.relation)
206
+ expect(query.count).to eq 1
207
+ expect(query.first_object).to eq subject.rdf_subject
208
+ end
209
+ end
210
+
211
+ context '#update_resource with related and then without related' do
212
+ # TODO add tests for autosaved relations
213
+ before do
214
+ subject.update_resource(related: true)
215
+ subject.update_resource # implicit false
216
+ end
217
+
218
+ it 'should not have related objects' do
219
+ expect(subject.resource.query(subject: person.rdf_subject)).to be_empty
220
+ expect(subject.resource.query(subject: concept.rdf_subject)).to be_empty
221
+ end
222
+
223
+ it 'should have embedded object relations' do
224
+ query = subject.resource.query(subject: part.rdf_subject, predicate: RDF::DC.relation)
225
+ expect(query.count).to eq 1
226
+ expect(query.first_object).to eq subject.rdf_subject
227
+ end
228
+
229
+ it 'should have related object relations' do
230
+ # many-to-many
231
+ query = person.resource.query(subject: person.rdf_subject, predicate: RDF::DC.relation)
232
+ expect(query.count).to eq 1
233
+ expect(query.first_object).to eq subject.rdf_subject
234
+
235
+ # one-sided has-many
236
+ expect(concept.resource.query(object: subject.rdf_subject)).to be_empty
237
+
238
+ # embedded-one
239
+ query = part.resource.query(subject: part.rdf_subject, predicate: RDF::DC.relation)
240
+ expect(query.count).to eq 1
241
+ expect(query.first_object).to eq subject.rdf_subject
242
+ end
243
+ end
244
+
245
+ context 'serializable' do
246
+ # TODO: contexts with relations and without
247
+ # expect(subject.as_jsonld(related: true)).to eq subject.as_jsonld
248
+ # expect(subject.as_qname(related: true)).to eq subject.as_qname
249
+ # expect(subject.as_framed_jsonld).to eq subject.as_jsonld
250
+
251
+ describe '#as_jsonld related: true' do
252
+ it 'should output a valid jsonld representation of itself and related' do
253
+ graph = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld related: true)
254
+ expect(subject.update_resource(related: true).to_hash).to eq graph.to_hash
255
+ end
256
+ end
257
+
258
+ describe '#as_qname related: true' do
259
+ it 'should output a valid qname representation of itself and related' do
260
+ # TODO
261
+ end
262
+ end
263
+
264
+ describe '#as_framed_jsonld' do
265
+ it 'should output a valid framed jsonld representation of itself and related' do
266
+ framed_graph = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_framed_jsonld)
267
+ related_graph = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld related: true)
268
+ expect(framed_graph.to_hash).to eq related_graph.to_hash
269
+ end
270
+ end
271
+ end
272
+
273
+ end
274
+
275
+ context 'with data' do
276
+ let(:subject) { Thing.new }
277
+
278
+ include_context 'with data'
279
+
280
+ it_behaves_like 'a Resource'
281
+ end
282
+
283
+ context 'with relations' do
284
+ let(:subject) { Thing.new }
285
+
286
+ include_context 'with data'
287
+ include_context 'with relations'
288
+
289
+ it_behaves_like 'a Resource'
290
+ end
291
+
27
292
  end