ladder 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -5
- data/README.md +151 -7
- data/ladder.gemspec +7 -7
- data/lib/ladder/resource.rb +25 -23
- data/lib/ladder/searchable.rb +39 -5
- data/lib/ladder/version.rb +1 -1
- data/spec/ladder/resource_spec.rb +82 -25
- data/spec/ladder/searchable_spec.rb +46 -4
- metadata +28 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec1270a31250bb0419ba153d1dee8db81788bed7
|
4
|
+
data.tar.gz: ffb8adb9b1ab0adcd83ff542642ebbb6342d4572
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 041d289b8105df18cb2dd1f3728a513abc5964807950bf6927ea2b73d85a9e2a060a9f962bf419b18260627554aa895028695c9857e08f3183334e208dc1b32e
|
7
|
+
data.tar.gz: 73f4d0acec4fadc96c77c29302a58ab2cdd7d2309e69fc3f29df6a6794b645d5888ad350d0cc25263fba7d083aa58583ba7966df8cecbcf23ed920eed6bb5f3d
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,7 +1,3 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
# We are pulling a specific ActiveTriples branch at the moment
|
7
|
-
gem 'active-triples', git: 'https://github.com/mjsuhonos/ActiveTriples.git', branch: 'feature/identifiable'
|
3
|
+
gemspec
|
data/README.md
CHANGED
@@ -328,16 +328,12 @@ Person.index as: :qname
|
|
328
328
|
=> :as_indexed_json
|
329
329
|
|
330
330
|
kimchy.as_indexed_json
|
331
|
-
# {
|
331
|
+
# => {
|
332
332
|
# "dc": {
|
333
|
-
# "description": {
|
334
|
-
# "en": "Real genius"
|
335
|
-
# }
|
333
|
+
# "description": { "en": "Real genius" }
|
336
334
|
# },
|
337
335
|
# "foaf": {
|
338
|
-
# "name": {
|
339
|
-
# "en": "Shay"
|
340
|
-
# }
|
336
|
+
# "name": { "en": "Shay" }
|
341
337
|
# },
|
342
338
|
# "rdf": {
|
343
339
|
# "type": "foaf:Person"
|
@@ -345,6 +341,154 @@ kimchy.as_indexed_json
|
|
345
341
|
# }
|
346
342
|
```
|
347
343
|
|
344
|
+
You can also index related objects as framed JSON-LD or hierarchical qname, by again using the `related: true` option:
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
class Project
|
348
|
+
include Ladder::Resource
|
349
|
+
include Ladder::Searchable
|
350
|
+
|
351
|
+
configure type: RDF::DOAP.Project
|
352
|
+
|
353
|
+
property :name, predicate: RDF::DOAP.name
|
354
|
+
property :description, predicate: RDF::DC.description
|
355
|
+
property :developers, predicate: RDF::DOAP.developer, class_name: 'Person'
|
356
|
+
end
|
357
|
+
|
358
|
+
Person.property :projects, predicate: RDF::FOAF.made, class_name: 'Project'
|
359
|
+
|
360
|
+
es = Project.new(name: 'ElasticSearch', description: 'You know, for search')
|
361
|
+
es.developers << kimchy
|
362
|
+
es.save
|
363
|
+
|
364
|
+
Person.index as: :jsonld, related: true
|
365
|
+
=> :as_indexed_json
|
366
|
+
Project.index as: :jsonld, related: true
|
367
|
+
=> :as_indexed_json
|
368
|
+
|
369
|
+
kimchy.as_indexed_json
|
370
|
+
# => {
|
371
|
+
# "@context": {
|
372
|
+
# "dc": "http://purl.org/dc/terms/",
|
373
|
+
# "doap": "http://usefulinc.com/ns/doap#",
|
374
|
+
# "foaf": "http://xmlns.com/foaf/0.1/"
|
375
|
+
# },
|
376
|
+
# "@id": "http://example.org/people/543b457b41697231c5000000",
|
377
|
+
# "@type": "foaf:Person",
|
378
|
+
# "dc:description": {
|
379
|
+
# "@language": "en",
|
380
|
+
# "@value": "Real genius"
|
381
|
+
# },
|
382
|
+
# "foaf:made": {
|
383
|
+
# "@id": "http://example.org/projects/544562c24169728b4e010000",
|
384
|
+
# "@type": "doap:Project",
|
385
|
+
# "dc:description": {
|
386
|
+
# "@language": "en",
|
387
|
+
# "@value": "You know, for search"
|
388
|
+
# },
|
389
|
+
# "doap:developer": {
|
390
|
+
# "@id": "http://example.org/people/543b457b41697231c5000000"
|
391
|
+
# },
|
392
|
+
# "doap:name": {
|
393
|
+
# "@language": "en",
|
394
|
+
# "@value": "ElasticSearch"
|
395
|
+
# }
|
396
|
+
# },
|
397
|
+
# "foaf:name": {
|
398
|
+
# "@language": "en",
|
399
|
+
# "@value": "Shay"
|
400
|
+
# }
|
401
|
+
# }
|
402
|
+
|
403
|
+
es.as_indexed_json
|
404
|
+
# => {
|
405
|
+
# "@context": {
|
406
|
+
# "dc": "http://purl.org/dc/terms/",
|
407
|
+
# "doap": "http://usefulinc.com/ns/doap#",
|
408
|
+
# "foaf": "http://xmlns.com/foaf/0.1/"
|
409
|
+
# },
|
410
|
+
# "@id": "http://example.org/projects/544562c24169728b4e010000",
|
411
|
+
# "@type": "doap:Project",
|
412
|
+
# "dc:description": {
|
413
|
+
# "@language": "en",
|
414
|
+
# "@value": "You know, for search"
|
415
|
+
# },
|
416
|
+
# "doap:developer": {
|
417
|
+
# "@id": "http://example.org/people/543b457b41697231c5000000",
|
418
|
+
# "@type": "foaf:Person",
|
419
|
+
# "dc:description": {
|
420
|
+
# "@language": "en",
|
421
|
+
# "@value": "Real genius"
|
422
|
+
# },
|
423
|
+
# "foaf:made": {
|
424
|
+
# "@id": "http://example.org/projects/544562c24169728b4e010000"
|
425
|
+
# },
|
426
|
+
# "foaf:name": {
|
427
|
+
# "@language": "en",
|
428
|
+
# "@value": "Shay"
|
429
|
+
# }
|
430
|
+
# },
|
431
|
+
# "doap:name": {
|
432
|
+
# "@language": "en",
|
433
|
+
# "@value": "ElasticSearch"
|
434
|
+
# }
|
435
|
+
# }
|
436
|
+
|
437
|
+
Person.index as: :qname, related: true
|
438
|
+
=> :as_indexed_json
|
439
|
+
Project.index as: :qname, related: true
|
440
|
+
=> :as_indexed_json
|
441
|
+
|
442
|
+
kimchy.as_indexed_json
|
443
|
+
# => {
|
444
|
+
# "dc": {
|
445
|
+
# "description": { "en": "Real genius" }
|
446
|
+
# },
|
447
|
+
# "foaf": {
|
448
|
+
# "made": {
|
449
|
+
# "dc": {
|
450
|
+
# "description": { "en": "You know, for search" }
|
451
|
+
# },
|
452
|
+
# "doap": {
|
453
|
+
# "developer": [ "people:544562b14169728b4e000000" ],
|
454
|
+
# "name": { "en": "ElasticSearch" }
|
455
|
+
# },
|
456
|
+
# "rdf": {
|
457
|
+
# "type": "doap:Project"
|
458
|
+
# }
|
459
|
+
# },
|
460
|
+
# "name": { "en": "Shay" }
|
461
|
+
# },
|
462
|
+
# "rdf": {
|
463
|
+
# "type": "foaf:Person"
|
464
|
+
# }
|
465
|
+
# }
|
466
|
+
|
467
|
+
es.as_indexed_json
|
468
|
+
# => {
|
469
|
+
# "dc": {
|
470
|
+
# "description": { "en": "You know, for search" }
|
471
|
+
# },
|
472
|
+
# "doap": {
|
473
|
+
# "developer": {
|
474
|
+
# "dc": {
|
475
|
+
# "description": { "en": "Real genius" }
|
476
|
+
# },
|
477
|
+
# "foaf": {
|
478
|
+
# "made": [ "projects:544562c24169728b4e010000" ],
|
479
|
+
# "name": { "en": "Shay" }
|
480
|
+
# },
|
481
|
+
# "rdf": {
|
482
|
+
# "type": "foaf:Person"
|
483
|
+
# }
|
484
|
+
# },
|
485
|
+
# "name": { "en": "ElasticSearch" }
|
486
|
+
# },
|
487
|
+
# "rdf": {
|
488
|
+
# "type": "doap:Project"
|
489
|
+
# }
|
490
|
+
# }
|
491
|
+
```
|
348
492
|
|
349
493
|
## Contributing
|
350
494
|
|
data/ladder.gemspec
CHANGED
@@ -21,13 +21,13 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
23
|
spec.add_dependency "mongoid", "~> 4.0"
|
24
|
-
spec.add_dependency "active-triples", "~> 0.
|
24
|
+
spec.add_dependency "active-triples", "~> 0.3"
|
25
25
|
spec.add_dependency "elasticsearch-model", "~> 0.1"
|
26
26
|
|
27
|
-
spec.add_development_dependency "bundler"
|
28
|
-
spec.add_development_dependency "pry"
|
29
|
-
spec.add_development_dependency "wirble"
|
30
|
-
spec.add_development_dependency "rspec"
|
31
|
-
spec.add_development_dependency "rake"
|
32
|
-
spec.add_development_dependency "yard"
|
27
|
+
spec.add_development_dependency "bundler"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "wirble"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
spec.add_development_dependency "yard"
|
33
33
|
end
|
data/lib/ladder/resource.rb
CHANGED
@@ -13,10 +13,11 @@ module Ladder::Resource
|
|
13
13
|
end
|
14
14
|
|
15
15
|
##
|
16
|
-
#
|
16
|
+
# Return JSON-LD representation
|
17
17
|
#
|
18
|
+
# @see ActiveTriples::Resource#dump
|
18
19
|
def as_jsonld(opts = {})
|
19
|
-
update_resource(opts.slice :related).dump(:jsonld, {standard_prefixes: true}.merge(opts))
|
20
|
+
JSON.parse update_resource(opts.slice :related).dump(:jsonld, {standard_prefixes: true}.merge(opts))
|
20
21
|
end
|
21
22
|
|
22
23
|
##
|
@@ -24,34 +25,35 @@ module Ladder::Resource
|
|
24
25
|
#
|
25
26
|
# @see ActiveTriples::Identifiable
|
26
27
|
def update_resource(opts = {})
|
27
|
-
relation_hash = opts[:related] ? relations : embedded_relations
|
28
|
-
|
29
28
|
super() do |name, prop|
|
30
|
-
|
31
|
-
|
29
|
+
# this is a literal property
|
30
|
+
if field_def = fields[name]
|
31
|
+
if field_def.localized?
|
32
|
+
value = read_attribute(name).map { |lang, val| RDF::Literal.new(val, language: lang) }
|
33
|
+
else
|
34
|
+
value = self.send(prop.term)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# this is a relation property
|
39
|
+
if relation_def = relations[name]
|
40
|
+
objects = self.send(prop.term).to_a
|
32
41
|
|
33
|
-
|
42
|
+
if opts[:related] or embedded_relations[name]
|
43
|
+
value = objects.map(&:update_resource)
|
34
44
|
|
35
|
-
|
36
|
-
|
37
|
-
if relation_hash.keys.include? name
|
38
|
-
obj.update_resource
|
39
|
-
obj.resource.set_value(relation_hash[name].inverse, self.rdf_subject) if relation_hash[name].inverse
|
40
|
-
obj
|
41
|
-
else
|
42
|
-
resource.delete [obj.rdf_subject] if resource.enum_subjects.include? obj.rdf_subject and ! opts[:related]
|
43
|
-
obj.rdf_subject
|
44
|
-
end
|
45
|
+
# update inverse relation properties
|
46
|
+
objects.each { |object| object.resource.set_value(relation_def.inverse, self.rdf_subject) } if relation_def.inverse
|
45
47
|
else
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
48
|
+
value = objects.map(&:rdf_subject)
|
49
|
+
|
50
|
+
# remove inverse relation properties
|
51
|
+
objects.each { |object| resource.delete [object.rdf_subject] }
|
51
52
|
end
|
53
|
+
|
52
54
|
end
|
53
55
|
|
54
|
-
resource.set_value(prop.predicate,
|
56
|
+
resource.set_value(prop.predicate, value)
|
55
57
|
end
|
56
58
|
|
57
59
|
resource
|
data/lib/ladder/searchable.rb
CHANGED
@@ -13,7 +13,7 @@ module Ladder::Searchable
|
|
13
13
|
##
|
14
14
|
# Generate a qname-based JSON representation
|
15
15
|
#
|
16
|
-
def as_qname
|
16
|
+
def as_qname(opts = {})
|
17
17
|
qname_hash = type.empty? ? {} : {rdf: {type: type.first.pname }}
|
18
18
|
|
19
19
|
resource_class.properties.each do |field_name, property|
|
@@ -23,7 +23,11 @@ module Ladder::Searchable
|
|
23
23
|
object = self.send(field_name)
|
24
24
|
|
25
25
|
if relations.keys.include? field_name
|
26
|
-
|
26
|
+
if opts[:related]
|
27
|
+
qname_hash[ns][name] = object.to_a.map { |obj| obj.as_qname }
|
28
|
+
else
|
29
|
+
qname_hash[ns][name] = object.to_a.map { |obj| "#{obj.class.name.underscore.pluralize}:#{obj.id}" }
|
30
|
+
end
|
27
31
|
elsif fields.keys.include? field_name
|
28
32
|
qname_hash[ns][name] = read_attribute(field_name)
|
29
33
|
end
|
@@ -32,17 +36,47 @@ module Ladder::Searchable
|
|
32
36
|
qname_hash
|
33
37
|
end
|
34
38
|
|
39
|
+
private
|
40
|
+
|
41
|
+
##
|
42
|
+
# Return a framed, compacted JSON-LD representation
|
43
|
+
# by embedding related objects from the graph
|
44
|
+
#
|
45
|
+
# NB: Will NOT embed related objects with same @type. Spec under discussion, see https://github.com/json-ld/json-ld.org/issues/110
|
46
|
+
def as_framed_jsonld
|
47
|
+
json_hash = as_jsonld related: true
|
48
|
+
context = json_hash['@context']
|
49
|
+
frame = {'@context' => context, '@type' => type.first.pname}
|
50
|
+
JSON::LD::API.compact(JSON::LD::API.frame(json_hash, frame), context)
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Force autosave of related documents using Mongoid-defined methods
|
55
|
+
# Required for explicit autosave prior to after_update index callbacks
|
56
|
+
#
|
57
|
+
def autosave
|
58
|
+
methods.select{|i| i[/autosave_documents/] }.each{|m| send m}
|
59
|
+
end
|
60
|
+
|
35
61
|
module ClassMethods
|
36
62
|
|
37
63
|
##
|
38
64
|
# Specify type of serialization to use for indexing
|
39
65
|
#
|
40
|
-
def index(opts={})
|
66
|
+
def index(opts = {})
|
41
67
|
case opts[:as]
|
42
68
|
when :jsonld
|
43
|
-
|
69
|
+
if opts[:related]
|
70
|
+
define_method(:as_indexed_json) { |opts = {}| autosave; as_framed_jsonld }
|
71
|
+
else
|
72
|
+
define_method(:as_indexed_json) { |opts = {}| as_jsonld }
|
73
|
+
end
|
44
74
|
when :qname
|
45
|
-
|
75
|
+
if opts[:related]
|
76
|
+
define_method(:as_indexed_json) { |opts = {}| as_qname related: true }
|
77
|
+
else
|
78
|
+
define_method(:as_indexed_json) { |opts = {}| as_qname }
|
79
|
+
end
|
46
80
|
else
|
47
81
|
define_method(:as_indexed_json) { |opts = {}| as_json(except: ['id', '_id']) }
|
48
82
|
end
|
data/lib/ladder/version.rb
CHANGED
@@ -38,8 +38,6 @@ describe Ladder::Resource do
|
|
38
38
|
|
39
39
|
class Part
|
40
40
|
include Ladder::Resource
|
41
|
-
embedded_in :thing
|
42
|
-
property :thing, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
43
41
|
end
|
44
42
|
|
45
43
|
# localized literal
|
@@ -56,10 +54,12 @@ describe Ladder::Resource do
|
|
56
54
|
subject.class.property :concepts, :predicate => RDF::DC.subject, :class_name => 'Concept'
|
57
55
|
subject.concepts << concept
|
58
56
|
|
59
|
-
# embedded
|
60
|
-
|
61
|
-
|
62
|
-
subject.
|
57
|
+
# embedded one
|
58
|
+
part.class.embedded_in :thing
|
59
|
+
part.class.property :thing, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
60
|
+
subject.class.embeds_one :part, cascade_callbacks: true
|
61
|
+
subject.class.property :part, :predicate => RDF::DC.hasPart, :class_name => 'Part'
|
62
|
+
subject.part = part
|
63
63
|
subject.save
|
64
64
|
end
|
65
65
|
|
@@ -72,7 +72,7 @@ describe Ladder::Resource do
|
|
72
72
|
expect(subject.title).to eq 'Comet in Moominland'
|
73
73
|
expect(subject.people.to_a).to include person
|
74
74
|
expect(subject.concepts.to_a).to include concept
|
75
|
-
expect(subject.
|
75
|
+
expect(subject.part).to eq part
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'should have reverse relations' do
|
@@ -206,7 +206,7 @@ describe Ladder::Resource do
|
|
206
206
|
expect(t = person.class.properties['thing']).to be_a ActiveTriples::NodeConfig
|
207
207
|
expect(t.predicate).to eq RDF::DC.relation
|
208
208
|
end
|
209
|
-
end
|
209
|
+
end
|
210
210
|
end
|
211
211
|
|
212
212
|
describe '#update_resource' do
|
@@ -225,14 +225,21 @@ describe Ladder::Resource do
|
|
225
225
|
end
|
226
226
|
|
227
227
|
it 'should have an embedded object' do
|
228
|
-
subject.resource.query(:subject =>
|
229
|
-
|
228
|
+
query = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.hasPart)
|
229
|
+
expect(query.count).to eq 1
|
230
|
+
|
231
|
+
query.each_statement do |s|
|
232
|
+
expect(s.object).to eq part.rdf_subject
|
230
233
|
end
|
231
234
|
end
|
232
235
|
|
233
236
|
it 'should have an embedded object relation' do
|
234
|
-
subject.resource.query(:subject =>
|
235
|
-
|
237
|
+
query = subject.resource.query(:subject => part.rdf_subject, :predicate => RDF::DC.relation)
|
238
|
+
expect(query.count).to eq 1
|
239
|
+
expect(query.to_hash).to eq part.resource.statements.to_hash
|
240
|
+
|
241
|
+
query.each_statement do |s|
|
242
|
+
expect(s.object).to eq subject.rdf_subject
|
236
243
|
end
|
237
244
|
end
|
238
245
|
|
@@ -261,30 +268,84 @@ describe Ladder::Resource do
|
|
261
268
|
end
|
262
269
|
|
263
270
|
it 'should have an embedded object' do
|
264
|
-
subject.resource.query(:subject =>
|
265
|
-
|
271
|
+
query = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.hasPart)
|
272
|
+
expect(query.count).to eq 1
|
273
|
+
|
274
|
+
query.each_statement do |s|
|
275
|
+
expect(s.object).to eq part.rdf_subject
|
266
276
|
end
|
267
277
|
end
|
268
278
|
|
269
279
|
it 'should have an embedded object relation' do
|
270
|
-
subject.resource.query(:subject =>
|
271
|
-
|
280
|
+
query = subject.resource.query(:subject => part.rdf_subject, :predicate => RDF::DC.relation)
|
281
|
+
expect(query.count).to eq 1
|
282
|
+
expect(query.to_hash).to eq part.resource.statements.to_hash
|
283
|
+
|
284
|
+
query.each_statement do |s|
|
285
|
+
expect(s.object).to eq subject.rdf_subject
|
272
286
|
end
|
273
287
|
end
|
274
288
|
|
275
289
|
it 'should have related objects' do
|
276
|
-
|
290
|
+
# many-to-many
|
291
|
+
query_creator = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.creator)
|
292
|
+
expect(query_creator.count).to eq 1
|
293
|
+
|
294
|
+
query_creator.each_statement do |s|
|
295
|
+
expect(s.object).to eq person.rdf_subject
|
296
|
+
end
|
297
|
+
|
298
|
+
# one-sided has-many
|
299
|
+
query_subject = subject.resource.query(:subject => subject.rdf_subject, :predicate => RDF::DC.subject)
|
300
|
+
expect(query_subject.count).to eq 1
|
301
|
+
|
302
|
+
query_subject.each_statement do |s|
|
277
303
|
expect(s.object).to eq concept.rdf_subject
|
278
304
|
end
|
279
|
-
|
280
|
-
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'should have related object relations' do
|
308
|
+
# many-to-many
|
309
|
+
query = person.resource.query(:subject => person.rdf_subject, :predicate => RDF::DC.relation)
|
310
|
+
expect(query.count).to eq 1
|
311
|
+
expect(query.to_hash).to eq person.resource.statements.to_hash
|
312
|
+
|
313
|
+
query.each_statement do |s|
|
314
|
+
expect(s.object).to eq subject.rdf_subject
|
281
315
|
end
|
316
|
+
|
317
|
+
# one-sided has-many
|
318
|
+
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
319
|
+
expect(concept.resource.statements).to be_empty
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context 'with related and then without related' do
|
324
|
+
include_context 'with data'
|
325
|
+
|
326
|
+
before do
|
327
|
+
subject.update_resource(:related => true)
|
328
|
+
subject.update_resource
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'should not have related objects' do
|
332
|
+
expect(subject.resource.query(:subject => person.rdf_subject)).to be_empty
|
333
|
+
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
282
334
|
end
|
283
335
|
|
284
336
|
it 'should have related object relations' do
|
285
|
-
|
337
|
+
# many-to-many
|
338
|
+
query = person.resource.query(:subject => person.rdf_subject, :predicate => RDF::DC.relation)
|
339
|
+
expect(query.count).to eq 1
|
340
|
+
expect(query.to_hash).to eq person.resource.statements.to_hash
|
341
|
+
|
342
|
+
query.each_statement do |s|
|
286
343
|
expect(s.object).to eq subject.rdf_subject
|
287
344
|
end
|
345
|
+
|
346
|
+
# one-sided has-many
|
347
|
+
expect(subject.resource.query(:subject => concept.rdf_subject)).to be_empty
|
348
|
+
expect(concept.resource.statements).to be_empty
|
288
349
|
end
|
289
350
|
end
|
290
351
|
end
|
@@ -292,12 +353,8 @@ describe Ladder::Resource do
|
|
292
353
|
describe '#as_jsonld' do
|
293
354
|
include_context 'with data'
|
294
355
|
|
295
|
-
before do
|
296
|
-
subject.update_resource
|
297
|
-
end
|
298
|
-
|
299
356
|
it 'should output a valid jsonld representation of itself' do
|
300
|
-
g = RDF::Graph.new << JSON::LD::API.toRdf(
|
357
|
+
g = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld)
|
301
358
|
expect(subject.resource.to_hash == g.to_hash).to be true
|
302
359
|
end
|
303
360
|
end
|
@@ -80,22 +80,22 @@ describe Ladder::Searchable do
|
|
80
80
|
it 'should exist in the index' do
|
81
81
|
results = subject.class.search('dc\:title.@value:moomin*')
|
82
82
|
expect(results.count).to eq 1
|
83
|
-
expect(results.first._source.to_hash).to eq
|
83
|
+
expect(results.first._source.to_hash).to eq subject.as_jsonld
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
describe '#index
|
88
|
+
describe '#index related' do
|
89
89
|
include_context 'with data'
|
90
90
|
|
91
91
|
before do
|
92
92
|
# related object
|
93
93
|
person.class.configure type: RDF::FOAF.Person
|
94
94
|
person.class.property :name, :predicate => RDF::FOAF.name
|
95
|
-
person.class.property :things, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
96
95
|
person.name = 'Tove Jansson'
|
97
96
|
|
98
97
|
# many-to-many relation
|
98
|
+
person.class.property :things, :predicate => RDF::DC.relation, :class_name => 'Thing'
|
99
99
|
subject.class.property :people, :predicate => RDF::DC.creator, :class_name => 'Person'
|
100
100
|
subject.people << person
|
101
101
|
end
|
@@ -150,6 +150,27 @@ describe Ladder::Searchable do
|
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
+
context 'with as_qname related' do
|
154
|
+
before do
|
155
|
+
person.class.index as: :qname, related: true
|
156
|
+
subject.class.index as: :qname, related: true
|
157
|
+
subject.save
|
158
|
+
Elasticsearch::Model.client.indices.flush
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should contain a embedded related object' do
|
162
|
+
results = subject.class.search('dc.creator.foaf.name.en:tove')
|
163
|
+
expect(results.count).to eq 1
|
164
|
+
expect(results.first._source['dc']['creator'].first).to eq Hashie::Mash.new person.as_qname
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should contain an embedded subject in the related object' do
|
168
|
+
results = person.class.search('dc.relation.dc.title.en:moomin*')
|
169
|
+
expect(results.count).to eq 1
|
170
|
+
expect(results.first._source['dc']['relation'].first).to eq Hashie::Mash.new subject.as_qname
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
153
174
|
context 'with as_jsonld' do
|
154
175
|
before do
|
155
176
|
person.class.index as: :jsonld
|
@@ -166,7 +187,7 @@ describe Ladder::Searchable do
|
|
166
187
|
it 'should include the related object in the index' do
|
167
188
|
results = person.class.search('foaf\:name.@value:tove')
|
168
189
|
expect(results.count).to eq 1
|
169
|
-
expect(results.first._source.to_hash).to eq
|
190
|
+
expect(results.first._source.to_hash).to eq person.as_jsonld
|
170
191
|
end
|
171
192
|
|
172
193
|
it 'should contain an ID for the subject' do
|
@@ -174,6 +195,27 @@ describe Ladder::Searchable do
|
|
174
195
|
expect(results.count).to eq 1
|
175
196
|
end
|
176
197
|
end
|
198
|
+
|
199
|
+
context 'with as_jsonld related' do
|
200
|
+
before do
|
201
|
+
person.class.index as: :jsonld, related: true
|
202
|
+
subject.class.index as: :jsonld, related: true
|
203
|
+
subject.save
|
204
|
+
Elasticsearch::Model.client.indices.flush
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should contain a embedded related object' do
|
208
|
+
results = subject.class.search('dc\:creator.foaf\:name.@value:tove')
|
209
|
+
expect(results.count).to eq 1
|
210
|
+
expect(results.first._source.to_hash['dc:creator']).to eq person.as_jsonld.except '@context'
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should contain an embedded subject in the related object' do
|
214
|
+
results = person.class.search('dc\:relation.dc\:title.@value:moomin*')
|
215
|
+
expect(results.count).to eq 1
|
216
|
+
expect(results.first._source.to_hash['dc:relation']).to eq subject.as_jsonld.except '@context'
|
217
|
+
end
|
218
|
+
end
|
177
219
|
end
|
178
220
|
|
179
221
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ladder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MJ Suhonos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: elasticsearch-model
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,86 +56,86 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: wirble
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: yard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0
|
131
|
+
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0
|
138
|
+
version: '0'
|
139
139
|
description: Ladder is a metadata framework for RDF modelling, persistence, and full-text
|
140
140
|
indexing.
|
141
141
|
email: mj@suhonos.ca
|