ladder 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.semver +2 -2
- data/README.md +37 -19
- data/lib/ladder.rb +5 -3
- data/lib/ladder/config.rb +73 -0
- data/lib/ladder/configurable.rb +26 -0
- data/lib/ladder/file.rb +10 -1
- data/lib/ladder/resource.rb +130 -60
- data/lib/ladder/resource/dynamic.rb +14 -10
- data/lib/ladder/resource/serializable.rb +22 -10
- data/lib/ladder/version.rb +1 -1
- data/spec/ladder/file_spec.rb +3 -8
- data/spec/ladder/resource/dynamic_spec.rb +19 -17
- data/spec/ladder/resource_spec.rb +43 -12
- data/spec/ladder/searchable/background_spec.rb +23 -13
- data/spec/ladder/searchable/file_spec.rb +2 -8
- data/spec/ladder/searchable/resource_spec.rb +20 -12
- data/spec/shared/file.rb +4 -2
- data/spec/shared/graph.jsonld +51 -6
- data/spec/shared/resource.rb +45 -180
- data/spec/shared/resource/dynamic.rb +149 -0
- data/spec/spec_helper.rb +16 -1
- metadata +6 -2
@@ -58,14 +58,13 @@ module Ladder
|
|
58
58
|
return unless self._context
|
59
59
|
|
60
60
|
self._context.each do |field_name, uri|
|
61
|
-
next if fields
|
61
|
+
next if fields[field_name]
|
62
|
+
next unless RDF::Vocabulary.find_term(uri)
|
62
63
|
|
63
|
-
|
64
|
-
create_accessors field_name
|
64
|
+
create_accessors field_name
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
end
|
66
|
+
# Apply instance properties to resource
|
67
|
+
resource_class.property(field_name.to_sym, predicate: RDF::Vocabulary.find_term(uri))
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
@@ -113,13 +112,15 @@ module Ladder
|
|
113
112
|
# @see Ladder::Resource#<<
|
114
113
|
#
|
115
114
|
# @param [RDF::Statement, Hash, Array] statement @see RDF::Statement#from
|
116
|
-
# @return [
|
115
|
+
# @return [Object, nil] the value inserted into the object
|
117
116
|
def <<(statement)
|
118
117
|
# ActiveTriples::Resource expects: RDF::Statement, Hash, or Array
|
119
118
|
statement = RDF::Statement.from(statement) unless statement.is_a? RDF::Statement
|
120
119
|
|
121
|
-
|
122
|
-
|
120
|
+
case statement.object
|
121
|
+
when resource_class.type then return # Don't store statically-defined types
|
122
|
+
when RDF::Node then return super # Delegate nodes (relations) to parent
|
123
|
+
end
|
123
124
|
|
124
125
|
if RDF.type == statement.predicate
|
125
126
|
# Store type information
|
@@ -131,9 +132,12 @@ module Ladder
|
|
131
132
|
end
|
132
133
|
|
133
134
|
# If we have an undefined predicate, then dynamically define it
|
134
|
-
return unless statement.predicate.qname
|
135
135
|
property statement.predicate.qname.last, predicate: statement.predicate unless field_from_predicate statement.predicate
|
136
136
|
|
137
|
+
if self._context && self._context.values.include?(statement.predicate.to_s)
|
138
|
+
send("#{self._context.key(statement.predicate.to_s)}=", statement.object.to_s)
|
139
|
+
end
|
140
|
+
|
137
141
|
super
|
138
142
|
end
|
139
143
|
|
@@ -1,17 +1,30 @@
|
|
1
1
|
require 'json/ld'
|
2
|
+
require 'rdf/turtle'
|
2
3
|
|
3
4
|
module Ladder
|
4
5
|
module Resource
|
5
6
|
module Serializable
|
7
|
+
##
|
8
|
+
# Return a Turtle representation for the resource
|
9
|
+
#
|
10
|
+
# @see ActiveTriples::Resource#dump
|
11
|
+
#
|
12
|
+
# @param [Hash] opts options to pass to ActiveTriples
|
13
|
+
# @option opts [Boolean] :related whether to include related resources (default: false)
|
14
|
+
# @return [String] a serialized Turtle version of the resource
|
15
|
+
def as_turtle(opts = { related: false })
|
16
|
+
update_resource(opts.slice :related).dump(:ttl, { standard_prefixes: true }.merge(opts))
|
17
|
+
end
|
18
|
+
|
6
19
|
##
|
7
20
|
# Return a JSON-LD representation for the resource
|
8
21
|
#
|
9
22
|
# @see ActiveTriples::Resource#dump
|
10
23
|
#
|
11
24
|
# @param [Hash] opts options to pass to ActiveTriples
|
12
|
-
# @option opts [Boolean] :related whether to include related resources
|
25
|
+
# @option opts [Boolean] :related whether to include related resources (default: false)
|
13
26
|
# @return [Hash] a serialized JSON-LD version of the resource
|
14
|
-
def as_jsonld(opts = {})
|
27
|
+
def as_jsonld(opts = { related: false })
|
15
28
|
JSON.parse update_resource(opts.slice :related).dump(:jsonld, { standard_prefixes: true }.merge(opts))
|
16
29
|
end
|
17
30
|
|
@@ -46,13 +59,11 @@ module Ladder
|
|
46
59
|
ns, name = property.predicate.qname
|
47
60
|
qname_hash[ns] ||= {}
|
48
61
|
|
49
|
-
if relations
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
elsif fields.keys.include? field_name
|
62
|
+
if relations[field_name]
|
63
|
+
qname_hash[ns][name] = opts[:related] ? send(field_name).to_a.map(&:as_qname) : send(field_name).to_a.map { |obj| "#{obj.class.name.underscore.pluralize}:#{obj.id}" }
|
64
|
+
end
|
65
|
+
|
66
|
+
if fields[field_name]
|
56
67
|
qname_hash[ns][name] = read_attribute(field_name)
|
57
68
|
end
|
58
69
|
|
@@ -60,7 +71,8 @@ module Ladder
|
|
60
71
|
qname_hash[ns].delete_if { |_k, v| v.blank? }
|
61
72
|
end
|
62
73
|
|
63
|
-
|
74
|
+
# Insert labels for boosting search score
|
75
|
+
{ rdfs: { label: update_resource(opts.slice :related).rdf_label } }.merge qname_hash
|
64
76
|
end
|
65
77
|
end
|
66
78
|
end
|
data/lib/ladder/version.rb
CHANGED
data/spec/ladder/file_spec.rb
CHANGED
@@ -2,24 +2,18 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::File do
|
4
4
|
before do
|
5
|
-
Mongoid.load!('mongoid.yml', :development)
|
6
|
-
Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
|
7
|
-
Mongoid.purge!
|
8
|
-
|
9
|
-
LADDER_BASE_URI ||= 'http://example.org'
|
10
|
-
|
11
5
|
class Datastream
|
12
6
|
include Ladder::File
|
13
7
|
end
|
14
8
|
end
|
15
9
|
|
16
10
|
after do
|
17
|
-
|
11
|
+
Ladder::Config.models.delete Datastream
|
18
12
|
Object.send(:remove_const, 'Datastream') if Object
|
19
13
|
end
|
20
14
|
|
21
15
|
shared_context 'with relations' do
|
22
|
-
let(:thing)
|
16
|
+
let(:thing) { Thing.new }
|
23
17
|
|
24
18
|
before do
|
25
19
|
class Thing
|
@@ -37,6 +31,7 @@ describe Ladder::File do
|
|
37
31
|
end
|
38
32
|
|
39
33
|
after do
|
34
|
+
Ladder::Config.models.delete Thing
|
40
35
|
Object.send(:remove_const, 'Thing') if Object
|
41
36
|
end
|
42
37
|
|
@@ -2,37 +2,39 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::Resource::Dynamic do
|
4
4
|
before do
|
5
|
-
Mongoid.load!('mongoid.yml', :development)
|
6
|
-
Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
|
7
|
-
Mongoid.purge!
|
8
|
-
|
9
|
-
LADDER_BASE_URI ||= 'http://example.org'
|
10
|
-
|
11
5
|
class Thing
|
12
6
|
include Ladder::Resource::Dynamic
|
7
|
+
|
8
|
+
# FIXME: DRY out this block
|
13
9
|
configure type: RDF::DC.BibliographicResource
|
14
10
|
|
15
|
-
|
16
|
-
property :alt,
|
17
|
-
|
11
|
+
property :title, predicate: RDF::DC.title # localized String
|
12
|
+
property :alt, predicate: RDF::DC.alternative, # non-localized String
|
13
|
+
localize: false
|
14
|
+
property :references, predicate: RDF::DC.references # URI
|
15
|
+
property :referenced, predicate: RDF::DC.isReferencedBy # Array
|
16
|
+
property :is_valid, predicate: RDF::DC.valid # Boolean
|
17
|
+
property :date, predicate: RDF::DC.date # Date
|
18
|
+
property :issued, predicate: RDF::DC.issued # DateTime
|
19
|
+
property :spatial, predicate: RDF::DC.spatial # Float
|
20
|
+
# property :conformsTo, predicate: RDF::DC.conformsTo # Hash
|
21
|
+
property :identifier, predicate: RDF::DC.identifier # Integer
|
22
|
+
# property :license, predicate: RDF::DC.license # Range
|
23
|
+
property :source, predicate: RDF::DC.source # Symbol
|
24
|
+
property :created, predicate: RDF::DC.created # Time
|
25
|
+
###
|
18
26
|
end
|
19
27
|
end
|
20
28
|
|
21
29
|
after do
|
22
|
-
|
30
|
+
Ladder::Config.models.delete Thing
|
23
31
|
Object.send(:remove_const, 'Thing') if Object
|
24
32
|
end
|
25
33
|
|
26
34
|
context 'with data' do
|
27
35
|
let(:subject) { Thing.new }
|
28
36
|
|
29
|
-
|
30
|
-
# non-localized literal
|
31
|
-
subject.alt = 'Mumintrollet pa kometjakt'
|
32
|
-
|
33
|
-
# localized literal
|
34
|
-
subject.title = 'Comet in Moominland'
|
35
|
-
end
|
37
|
+
include_context 'with data'
|
36
38
|
|
37
39
|
it_behaves_like 'a Resource'
|
38
40
|
it_behaves_like 'a Dynamic Resource'
|
@@ -2,25 +2,32 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::Resource do
|
4
4
|
before do
|
5
|
-
Mongoid.load!('mongoid.yml', :development)
|
6
|
-
Mongoid.logger.level = Moped.logger.level = Logger::DEBUG
|
7
|
-
Mongoid.purge!
|
8
|
-
|
9
|
-
LADDER_BASE_URI ||= 'http://example.org'
|
10
|
-
|
11
5
|
class Thing
|
12
6
|
include Ladder::Resource
|
7
|
+
|
8
|
+
# FIXME: DRY out this block
|
13
9
|
configure type: RDF::DC.BibliographicResource
|
14
10
|
|
15
|
-
|
16
|
-
property :alt,
|
17
|
-
|
18
|
-
property :
|
11
|
+
property :title, predicate: RDF::DC.title # localized String
|
12
|
+
property :alt, predicate: RDF::DC.alternative, # non-localized String
|
13
|
+
localize: false
|
14
|
+
property :references, predicate: RDF::DC.references # URI
|
15
|
+
property :referenced, predicate: RDF::DC.isReferencedBy # Array
|
16
|
+
property :is_valid, predicate: RDF::DC.valid # Boolean
|
17
|
+
property :date, predicate: RDF::DC.date # Date
|
18
|
+
property :issued, predicate: RDF::DC.issued # DateTime
|
19
|
+
property :spatial, predicate: RDF::DC.spatial # Float
|
20
|
+
# property :conformsTo, predicate: RDF::DC.conformsTo # Hash
|
21
|
+
property :identifier, predicate: RDF::DC.identifier # Integer
|
22
|
+
# property :license, predicate: RDF::DC.license # Range
|
23
|
+
property :source, predicate: RDF::DC.source # Symbol
|
24
|
+
property :created, predicate: RDF::DC.created # Time
|
25
|
+
###
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
29
|
after do
|
23
|
-
|
30
|
+
Ladder::Config.models.delete Thing
|
24
31
|
Object.send(:remove_const, 'Thing') if Object
|
25
32
|
end
|
26
33
|
|
@@ -47,7 +54,7 @@ describe Ladder::Resource do
|
|
47
54
|
configure type: RDF::DC.PhysicalResource
|
48
55
|
|
49
56
|
embedded_in :thing
|
50
|
-
property :thing, predicate: RDF::DC.
|
57
|
+
property :thing, predicate: RDF::DC.isPartOf, class_name: 'Thing'
|
51
58
|
end
|
52
59
|
|
53
60
|
# many-to-many
|
@@ -63,6 +70,10 @@ describe Ladder::Resource do
|
|
63
70
|
end
|
64
71
|
|
65
72
|
after do
|
73
|
+
Ladder::Config.models.delete Person
|
74
|
+
Ladder::Config.models.delete Concept
|
75
|
+
Ladder::Config.models.delete Part
|
76
|
+
|
66
77
|
Object.send(:remove_const, 'Person') if Object
|
67
78
|
Object.send(:remove_const, 'Concept') if Object
|
68
79
|
Object.send(:remove_const, 'Part') if Object
|
@@ -77,6 +88,26 @@ describe Ladder::Resource do
|
|
77
88
|
it_behaves_like 'a Resource'
|
78
89
|
end
|
79
90
|
|
91
|
+
context 'with subclass' do
|
92
|
+
before do
|
93
|
+
class Subthing < Thing
|
94
|
+
# types are not inherited, so we must set it explicitly
|
95
|
+
configure type: RDF::DC.BibliographicResource
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
after do
|
100
|
+
Ladder::Config.models.delete Subthing
|
101
|
+
Object.send(:remove_const, 'Subthing') if Object
|
102
|
+
end
|
103
|
+
|
104
|
+
let(:subject) { Subthing.new }
|
105
|
+
|
106
|
+
include_context 'with data'
|
107
|
+
|
108
|
+
it_behaves_like 'a Resource'
|
109
|
+
end
|
110
|
+
|
80
111
|
context 'with relations' do
|
81
112
|
let(:subject) { Thing.new }
|
82
113
|
|
@@ -2,23 +2,30 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::Searchable::Background do
|
4
4
|
before do
|
5
|
-
|
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'
|
5
|
+
Elasticsearch::Client.new(host: 'localhost:9200', log: true).indices.delete index: '_all'
|
13
6
|
|
14
7
|
class Thing
|
15
8
|
include Ladder::Resource
|
16
9
|
include Ladder::Searchable::Background
|
10
|
+
|
11
|
+
# FIXME: DRY out this block
|
17
12
|
configure type: RDF::DC.BibliographicResource
|
18
13
|
|
19
|
-
|
20
|
-
property :alt,
|
21
|
-
|
14
|
+
property :title, predicate: RDF::DC.title # localized String
|
15
|
+
property :alt, predicate: RDF::DC.alternative, # non-localized String
|
16
|
+
localize: false
|
17
|
+
property :references, predicate: RDF::DC.references # URI
|
18
|
+
property :referenced, predicate: RDF::DC.isReferencedBy # Array
|
19
|
+
property :is_valid, predicate: RDF::DC.valid # Boolean
|
20
|
+
property :date, predicate: RDF::DC.date # Date
|
21
|
+
property :issued, predicate: RDF::DC.issued # DateTime
|
22
|
+
property :spatial, predicate: RDF::DC.spatial # Float
|
23
|
+
# property :conformsTo, predicate: RDF::DC.conformsTo # Hash
|
24
|
+
property :identifier, predicate: RDF::DC.identifier # Integer
|
25
|
+
# property :license, predicate: RDF::DC.license # Range
|
26
|
+
property :source, predicate: RDF::DC.source # Symbol
|
27
|
+
property :created, predicate: RDF::DC.created # Time
|
28
|
+
###
|
22
29
|
end
|
23
30
|
|
24
31
|
class Datastream
|
@@ -28,13 +35,15 @@ describe Ladder::Searchable::Background do
|
|
28
35
|
end
|
29
36
|
|
30
37
|
after do
|
31
|
-
|
38
|
+
Ladder::Config.models.delete Thing
|
39
|
+
Ladder::Config.models.delete Datastream
|
40
|
+
|
32
41
|
Object.send(:remove_const, 'Thing') if Object
|
33
42
|
Object.send(:remove_const, 'Datastream') if Object
|
34
43
|
end
|
35
44
|
|
36
45
|
shared_context 'with relations' do
|
37
|
-
let(:person)
|
46
|
+
let(:person) { Person.new }
|
38
47
|
|
39
48
|
before do
|
40
49
|
class Person
|
@@ -48,6 +57,7 @@ describe Ladder::Searchable::Background do
|
|
48
57
|
end
|
49
58
|
|
50
59
|
after do
|
60
|
+
Ladder::Config.models.delete Person
|
51
61
|
Object.send(:remove_const, 'Person') if Object
|
52
62
|
end
|
53
63
|
end
|
@@ -2,14 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::Searchable::File do
|
4
4
|
before do
|
5
|
-
|
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'
|
5
|
+
Elasticsearch::Client.new(host: 'localhost:9200', log: true).indices.delete index: '_all'
|
13
6
|
|
14
7
|
class Datastream
|
15
8
|
include Ladder::File
|
@@ -18,6 +11,7 @@ describe Ladder::Searchable::File do
|
|
18
11
|
end
|
19
12
|
|
20
13
|
after do
|
14
|
+
Ladder::Config.models.delete Datastream
|
21
15
|
Object.send(:remove_const, 'Datastream') if Object
|
22
16
|
end
|
23
17
|
|
@@ -2,28 +2,35 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Ladder::Searchable::Resource do
|
4
4
|
before do
|
5
|
-
|
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'
|
5
|
+
Elasticsearch::Client.new(host: 'localhost:9200', log: true).indices.delete index: '_all'
|
13
6
|
|
14
7
|
class Thing
|
15
8
|
include Ladder::Resource
|
16
9
|
include Ladder::Searchable
|
10
|
+
|
11
|
+
# FIXME: DRY out this block
|
17
12
|
configure type: RDF::DC.BibliographicResource
|
18
13
|
|
19
|
-
|
20
|
-
property :alt,
|
21
|
-
|
14
|
+
property :title, predicate: RDF::DC.title # localized String
|
15
|
+
property :alt, predicate: RDF::DC.alternative, # non-localized String
|
16
|
+
localize: false
|
17
|
+
property :references, predicate: RDF::DC.references # URI
|
18
|
+
property :referenced, predicate: RDF::DC.isReferencedBy # Array
|
19
|
+
property :is_valid, predicate: RDF::DC.valid # Boolean
|
20
|
+
property :date, predicate: RDF::DC.date # Date
|
21
|
+
property :issued, predicate: RDF::DC.issued # DateTime
|
22
|
+
property :spatial, predicate: RDF::DC.spatial # Float
|
23
|
+
# property :conformsTo, predicate: RDF::DC.conformsTo # Hash
|
24
|
+
property :identifier, predicate: RDF::DC.identifier # Integer
|
25
|
+
# property :license, predicate: RDF::DC.license # Range
|
26
|
+
property :source, predicate: RDF::DC.source # Symbol
|
27
|
+
property :created, predicate: RDF::DC.created # Time
|
28
|
+
###
|
22
29
|
end
|
23
30
|
end
|
24
31
|
|
25
32
|
after do
|
26
|
-
|
33
|
+
Ladder::Config.models.delete Thing
|
27
34
|
Object.send(:remove_const, 'Thing') if Object
|
28
35
|
end
|
29
36
|
|
@@ -42,6 +49,7 @@ describe Ladder::Searchable::Resource do
|
|
42
49
|
end
|
43
50
|
|
44
51
|
after do
|
52
|
+
Ladder::Config.models.delete Person
|
45
53
|
Object.send(:remove_const, 'Person') if Object
|
46
54
|
end
|
47
55
|
end
|