ladder 0.0.4 → 0.1.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.
- 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
|