active-triples 0.1.0 → 0.1.1
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/AUTHORS +2 -2
- data/Guardfile +9 -0
- data/README.md +129 -15
- data/WAIVER +5 -0
- data/active-triples.gemspec +2 -0
- data/lib/active_triples/configurable.rb +18 -3
- data/lib/active_triples/list.rb +7 -0
- data/lib/active_triples/node_config.rb +1 -0
- data/lib/active_triples/properties.rb +20 -32
- data/lib/active_triples/resource.rb +138 -26
- data/lib/active_triples/term.rb +20 -17
- data/lib/active_triples/version.rb +1 -1
- data/spec/active_triples/configurable_spec.rb +37 -0
- data/spec/{rdf_list_spec.rb → active_triples/list_spec.rb} +47 -35
- data/spec/{rdf_nested_attributes_spec.rb → active_triples/nested_attributes_spec.rb} +9 -9
- data/spec/{rdf_properties_spec.rb → active_triples/properties_spec.rb} +0 -23
- data/spec/{rdf_repositories_spec.rb → active_triples/repositories_spec.rb} +0 -0
- data/spec/{rdf_resource_spec.rb → active_triples/resource_spec.rb} +18 -9
- data/spec/pragmatic_context_spec.rb +53 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/active_model_lint.rb +4 -4
- metadata +40 -7
data/lib/active_triples/term.rb
CHANGED
@@ -38,17 +38,16 @@ module ActiveTriples
|
|
38
38
|
|
39
39
|
def build(attributes={})
|
40
40
|
new_subject = attributes.key?('id') ? attributes.delete('id') : RDF::Node.new
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
node
|
41
|
+
make_node(new_subject).tap do |node|
|
42
|
+
node.attributes = attributes
|
43
|
+
if parent.kind_of? List::ListResource
|
44
|
+
parent.list << node
|
45
|
+
elsif node.kind_of? RDF::List
|
46
|
+
self.push node.rdf_subject
|
47
|
+
else
|
48
|
+
self.push node
|
49
|
+
end
|
50
|
+
end
|
52
51
|
end
|
53
52
|
|
54
53
|
def first_or_create(attributes={})
|
@@ -74,7 +73,7 @@ module ActiveTriples
|
|
74
73
|
end
|
75
74
|
|
76
75
|
def type_property
|
77
|
-
{:multivalue => true, :predicate => RDF.type}
|
76
|
+
{ :multivalue => true, :predicate => RDF.type }
|
78
77
|
end
|
79
78
|
|
80
79
|
def reset!
|
@@ -126,8 +125,7 @@ module ActiveTriples
|
|
126
125
|
end
|
127
126
|
|
128
127
|
def predicate
|
129
|
-
|
130
|
-
property
|
128
|
+
property.kind_of?(RDF::URI) ? property : property_config[:predicate]
|
131
129
|
end
|
132
130
|
|
133
131
|
def valid_datatype?(val)
|
@@ -136,9 +134,14 @@ module ActiveTriples
|
|
136
134
|
|
137
135
|
# Converts an object to the appropriate class.
|
138
136
|
def convert_object(value)
|
139
|
-
|
140
|
-
|
141
|
-
|
137
|
+
case value
|
138
|
+
when RDF::Literal
|
139
|
+
value.object
|
140
|
+
when RDF::Resource
|
141
|
+
make_node(value)
|
142
|
+
else
|
143
|
+
value
|
144
|
+
end
|
142
145
|
end
|
143
146
|
|
144
147
|
##
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
describe ActiveTriples::Configurable do
|
3
|
+
before do
|
4
|
+
class DummyConfigurable
|
5
|
+
extend ActiveTriples::Configurable
|
6
|
+
end
|
7
|
+
end
|
8
|
+
after do
|
9
|
+
Object.send(:remove_const, "DummyConfigurable")
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#configure' do
|
13
|
+
before do
|
14
|
+
DummyConfigurable.configure base_uri: "http://example.org/base", type: RDF::RDFS.Class, rdf_label: RDF::DC.title
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should set a base uri' do
|
18
|
+
expect(DummyConfigurable.base_uri).to eq "http://example.org/base"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should set an rdf_label' do
|
22
|
+
expect(DummyConfigurable.rdf_label).to eq RDF::DC.title
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should set a type' do
|
26
|
+
expect(DummyConfigurable.type).to eq RDF::RDFS.Class
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#rdf_type' do
|
31
|
+
it "should set the type the old way" do
|
32
|
+
DummyConfigurable.should_receive(:configure).with(type: RDF::RDFS.Class).and_call_original
|
33
|
+
DummyConfigurable.rdf_type(RDF::RDFS.Class)
|
34
|
+
expect(DummyConfigurable.type).to eq RDF::RDFS.Class
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -39,27 +39,27 @@ describe ActiveTriples::List do
|
|
39
39
|
subject { ds.elementList.build}
|
40
40
|
|
41
41
|
it "should insert at the end" do
|
42
|
-
subject.
|
43
|
-
subject.size.
|
42
|
+
expect(subject).to be_kind_of DemoList::List
|
43
|
+
expect(subject.size).to eq 0
|
44
44
|
subject[1] = DemoList::List::TopicElement.new
|
45
|
-
subject.size.
|
45
|
+
expect(subject.size).to eq 2
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should insert at the head" do
|
49
|
-
subject.
|
50
|
-
subject.size.
|
49
|
+
expect(subject).to be_kind_of DemoList::List
|
50
|
+
expect(subject.size).to eq 0
|
51
51
|
subject[0] = DemoList::List::TopicElement.new
|
52
|
-
subject.size.
|
52
|
+
expect(subject.size).to eq 1
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "that has 4 elements" do
|
56
56
|
before do
|
57
57
|
subject[3] = DemoList::List::TopicElement.new
|
58
|
-
subject.size.
|
58
|
+
expect(subject.size).to eq 4
|
59
59
|
end
|
60
60
|
it "should insert in the middle" do
|
61
61
|
subject[1] = DemoList::List::TopicElement.new
|
62
|
-
subject.size.
|
62
|
+
expect(subject.size).to eq 4
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -87,7 +87,7 @@ describe ActiveTriples::List do
|
|
87
87
|
describe "an empty list" do
|
88
88
|
subject { DemoList.new.elementList.build }
|
89
89
|
it "should have to_ary" do
|
90
|
-
subject.to_ary.
|
90
|
+
expect(subject.to_ary).to eq []
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -97,17 +97,17 @@ describe ActiveTriples::List do
|
|
97
97
|
let!(:topic) { list.topicElement.build }
|
98
98
|
|
99
99
|
it "should have to_ary" do
|
100
|
-
list.to_ary.size.
|
101
|
-
list.to_ary.first.class.
|
100
|
+
expect(list.to_ary.size).to eq 1
|
101
|
+
expect(list.to_ary.first.class).to eq DemoList::List::TopicElement
|
102
102
|
end
|
103
103
|
|
104
104
|
it "should be able to be cleared" do
|
105
105
|
list.topicElement.build
|
106
106
|
list.topicElement.build
|
107
107
|
list.topicElement.build
|
108
|
-
list.size.
|
108
|
+
expect(list.size).to eq 4
|
109
109
|
list.clear
|
110
|
-
list.size.
|
110
|
+
expect(list.size).to eq 0
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -137,47 +137,59 @@ END
|
|
137
137
|
subject
|
138
138
|
end
|
139
139
|
it "should have a subject" do
|
140
|
-
subject.rdf_subject.to_s.
|
140
|
+
expect(subject.rdf_subject.to_s).to eq "http://example.org/foo"
|
141
141
|
end
|
142
142
|
|
143
143
|
let (:list) { subject.elementList.first }
|
144
144
|
|
145
145
|
it "should have fields" do
|
146
|
-
list.first.rdf_subject.
|
147
|
-
list[1].
|
148
|
-
list[1].elementValue.
|
149
|
-
list[2].rdf_subject.
|
150
|
-
list[3].
|
151
|
-
list[3].elementValue.
|
146
|
+
expect(list.first.rdf_subject).to eq "http://library.ucsd.edu/ark:/20775/bbXXXXXXX6"
|
147
|
+
expect(list[1]).to be_kind_of DemoList::List::TopicElement
|
148
|
+
expect(list[1].elementValue).to eq ["Relations with Mexican Americans"]
|
149
|
+
expect(list[2].rdf_subject).to eq "http://library.ucsd.edu/ark:/20775/bbXXXXXXX4"
|
150
|
+
expect(list[3]).to be_kind_of DemoList::List::TemporalElement
|
151
|
+
expect(list[3].elementValue).to eq ["20th century"]
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should have each" do
|
155
155
|
foo = []
|
156
156
|
list.each { |n| foo << n.class }
|
157
|
-
foo.
|
157
|
+
expect(foo).to eq [ActiveTriples::Resource, DemoList::List::TopicElement, ActiveTriples::Resource, DemoList::List::TemporalElement]
|
158
158
|
end
|
159
159
|
|
160
160
|
it "should have to_ary" do
|
161
161
|
ary = list.to_ary
|
162
|
-
ary.size.
|
163
|
-
ary[1].elementValue.
|
162
|
+
expect(ary.size).to eq 4
|
163
|
+
expect(ary[1].elementValue).to eq ['Relations with Mexican Americans']
|
164
164
|
end
|
165
165
|
|
166
166
|
it "should have size" do
|
167
|
-
list.size.
|
167
|
+
expect(list.size).to eq 4
|
168
168
|
end
|
169
169
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
170
|
+
|
171
|
+
describe "updating fields" do
|
172
|
+
it "stores the values in a containing node" do
|
173
|
+
list[3].elementValue = ["1900s"]
|
174
|
+
doc = Nokogiri::XML(subject.dump :rdfxml)
|
175
|
+
ns = {rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", mads: "http://www.loc.gov/mads/rdf/v1#"}
|
176
|
+
expect(doc.xpath('/rdf:RDF/mads:ComplexSubject/@rdf:about', ns).map(&:value)).to eq ["http://example.org/foo"]
|
177
|
+
expect(doc.xpath('//mads:ComplexSubject/mads:elementList/@rdf:parseType', ns).map(&:value)).to eq ["Collection"]
|
178
|
+
expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 1]/@rdf:about', ns).map(&:value)).to eq ["http://library.ucsd.edu/ark:/20775/bbXXXXXXX6"]
|
179
|
+
expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 2]/mads:elementValue', ns).map(&:text)).to eq ["Relations with Mexican Americans"]
|
180
|
+
expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 3]/@rdf:about', ns).map(&:value)).to eq ["http://library.ucsd.edu/ark:/20775/bbXXXXXXX4"]
|
181
|
+
expect(doc.xpath('//mads:ComplexSubject/mads:elementList/*[position() = 4]/mads:elementValue', ns).map(&:text)).to eq ["1900s"]
|
182
|
+
expect(RDF::List.new(list.rdf_subject, subject.graph)).to be_valid
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should be a valid list" do
|
186
|
+
list << "Val"
|
187
|
+
# TODO this is a workaround for https://github.com/projecthydra/active_fedora/issues/444
|
188
|
+
# remove the following line when #444 is closed.
|
189
|
+
list.resource.persist!
|
190
|
+
expect(RDF::List.new(list.rdf_subject, subject.graph)).to be_valid
|
191
|
+
end
|
192
|
+
end
|
181
193
|
end
|
182
194
|
end
|
183
195
|
|
@@ -100,14 +100,14 @@ describe "nesting attribute behavior" do
|
|
100
100
|
subject { ComplexResource::PersonalName.new }
|
101
101
|
it "should accept a hash" do
|
102
102
|
subject.elementList_attributes = [{ topicElement_attributes: {'0' => { elementValue:"Quantum Behavior" }, '1' => { elementValue:"Wave Function" }}}]
|
103
|
-
subject.elementList.first[0].elementValue.
|
104
|
-
subject.elementList.first[1].elementValue.
|
103
|
+
expect(subject.elementList.first[0].elementValue).to eq ["Quantum Behavior"]
|
104
|
+
expect(subject.elementList.first[1].elementValue).to eq ["Wave Function"]
|
105
105
|
|
106
106
|
end
|
107
107
|
it "should accept an array" do
|
108
108
|
subject.elementList_attributes = [{ topicElement_attributes: [{ elementValue:"Quantum Behavior" }, { elementValue:"Wave Function" }]}]
|
109
|
-
subject.elementList.first[0].elementValue.
|
110
|
-
subject.elementList.first[1].elementValue.
|
109
|
+
expect(subject.elementList.first[0].elementValue).to eq ["Quantum Behavior"]
|
110
|
+
expect(subject.elementList.first[1].elementValue).to eq ["Wave Function"]
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -118,10 +118,10 @@ describe "nesting attribute behavior" do
|
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'should have attributes' do
|
121
|
-
subject.topic[0].elementList.first[0].elementValue.
|
122
|
-
subject.topic[1].elementList.first[0].elementValue.
|
123
|
-
subject.personalName.first.elementList.first.fullNameElement.
|
124
|
-
subject.personalName.first.elementList.first.dateNameElement.
|
121
|
+
expect(subject.topic[0].elementList.first[0].elementValue).to eq ["Cosmology"]
|
122
|
+
expect(subject.topic[1].elementList.first[0].elementValue).to eq ["Quantum Behavior"]
|
123
|
+
expect(subject.personalName.first.elementList.first.fullNameElement).to eq ["Jefferson, Thomas"]
|
124
|
+
expect(subject.personalName.first.elementList.first.dateNameElement).to eq ["1743-1826"]
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'should build nodes with ids' do
|
@@ -171,7 +171,7 @@ describe "nesting attribute behavior" do
|
|
171
171
|
it "should update nested objects" do
|
172
172
|
subject.parts_attributes= [{id: replace_object_id, label: "Universal Joint"}, {label:"Oil Pump"}, {id: remove_object_id, _destroy: '1', label: "bar1 uno"}]
|
173
173
|
|
174
|
-
subject.parts.map{|p| p.label.first}.
|
174
|
+
expect(subject.parts.map{|p| p.label.first}).to eq ['Alternator', 'Universal Joint', 'Transmission', 'Oil Pump']
|
175
175
|
|
176
176
|
end
|
177
177
|
it "create a new object when the id is provided" do
|
@@ -10,28 +10,6 @@ describe ActiveTriples::Properties do
|
|
10
10
|
Object.send(:remove_const, "DummyProperties")
|
11
11
|
end
|
12
12
|
|
13
|
-
describe '#map_predicates' do
|
14
|
-
before do
|
15
|
-
DummyProperties.map_predicates do |map|
|
16
|
-
map.title(:in => RDF::DC, :class_name => RDF::Literal) do |index|
|
17
|
-
index.as :facetable, :searchable
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should set a property' do
|
23
|
-
expect(DummyProperties.properties).to include :title
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should set index behaviors" do
|
27
|
-
expect(DummyProperties.properties[:title][:behaviors]).to eq [:facetable, :searchable]
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should set a class name" do
|
31
|
-
expect(DummyProperties.properties[:title][:class_name]).to eq RDF::Literal
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
13
|
describe '#property' do
|
36
14
|
it 'should set a property' do
|
37
15
|
DummyProperties.property :title, :predicate => RDF::DC.title
|
@@ -59,7 +37,6 @@ describe ActiveTriples::Properties do
|
|
59
37
|
DummyProperties.property :title, :predicate => RDF::DC.title, :class_name => "FakeClassName"
|
60
38
|
expect(DummyProperties.properties[:title][:class_name]).to eq "FakeClassName"
|
61
39
|
end
|
62
|
-
|
63
40
|
end
|
64
41
|
|
65
42
|
context "when using a subclass" do
|
File without changes
|
@@ -22,7 +22,7 @@ describe ActiveTriples::Resource do
|
|
22
22
|
|
23
23
|
describe 'rdf_subject' do
|
24
24
|
it "should be a blank node if we haven't set it" do
|
25
|
-
expect(subject.rdf_subject.node?).to
|
25
|
+
expect(subject.rdf_subject.node?).to be true
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should be settable" do
|
@@ -43,15 +43,15 @@ describe ActiveTriples::Resource do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'should update graph subjects' do
|
46
|
-
expect(subject.has_statement?(RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland')))).to
|
46
|
+
expect(subject.has_statement?(RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland')))).to be true
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should update graph objects' do
|
50
|
-
expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject))).to
|
50
|
+
expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject))).to be true
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'should leave other uris alone' do
|
54
|
-
expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land'))).to
|
54
|
+
expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land'))).to be true
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -70,7 +70,7 @@ describe ActiveTriples::Resource do
|
|
70
70
|
context 'with a repository' do
|
71
71
|
before do
|
72
72
|
repository = RDF::Repository.new
|
73
|
-
subject.
|
73
|
+
allow(subject).to receive(:repository).and_return(repository)
|
74
74
|
end
|
75
75
|
|
76
76
|
context "when the object is new" do
|
@@ -123,8 +123,8 @@ describe ActiveTriples::Resource do
|
|
123
123
|
|
124
124
|
before do
|
125
125
|
@repo = RDF::Repository.new
|
126
|
-
subject.class.
|
127
|
-
subject.
|
126
|
+
allow(subject.class).to receive(:repository).and_return(nil)
|
127
|
+
allow(subject).to receive(:repository).and_return(@repo)
|
128
128
|
subject.title = "bla"
|
129
129
|
subject.persist!
|
130
130
|
end
|
@@ -156,8 +156,8 @@ describe ActiveTriples::Resource do
|
|
156
156
|
subject { DummyLicense.new('http://example.org/cc')}
|
157
157
|
|
158
158
|
it 'should return true' do
|
159
|
-
expect(subject.destroy!).to
|
160
|
-
expect(subject.destroy).to
|
159
|
+
expect(subject.destroy!).to be true
|
160
|
+
expect(subject.destroy).to be true
|
161
161
|
end
|
162
162
|
|
163
163
|
it 'should delete the graph' do
|
@@ -188,6 +188,15 @@ describe ActiveTriples::Resource do
|
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
|
+
describe 'class_name' do
|
192
|
+
it 'should raise an error when not a class or string' do
|
193
|
+
DummyResource.property :relation, :predicate => RDF::DC.relation, :class_name => RDF::URI('http://example.org')
|
194
|
+
d = DummyResource.new
|
195
|
+
d.relation = RDF::DC.type
|
196
|
+
expect { d.relation.first }.to raise_error "class_name for relation is a RDF::URI; must be a class"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
191
200
|
describe 'attributes' do
|
192
201
|
before do
|
193
202
|
subject.license = license
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pragmatic_context'
|
3
|
+
|
4
|
+
describe 'PragmaticContext integration' do
|
5
|
+
before do
|
6
|
+
class DummyLicense < ActiveTriples::Resource
|
7
|
+
include PragmaticContext::Contextualizable
|
8
|
+
property :title, :predicate => RDF::DC.title
|
9
|
+
|
10
|
+
contextualize :title, :as => RDF::DC.title.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
class DummyResource < ActiveTriples::Resource
|
14
|
+
include PragmaticContext::Contextualizable
|
15
|
+
|
16
|
+
configure :type => RDF::URI('http://example.org/SomeClass')
|
17
|
+
property :license, :predicate => RDF::DC.license, :class_name => DummyLicense
|
18
|
+
property :title, :predicate => RDF::DC.title
|
19
|
+
|
20
|
+
contextualize :title, :as => RDF::DC.title.to_s
|
21
|
+
contextualize :license, :as => RDF::DC.license.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
license.title = 'cc'
|
25
|
+
subject.title = 'my resource'
|
26
|
+
subject.license = license
|
27
|
+
subject.license << RDF::Literal('Creative Commons')
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
Object.send(:remove_const, "DummyResource") if Object
|
32
|
+
Object.send(:remove_const, "DummyLicense") if Object
|
33
|
+
end
|
34
|
+
|
35
|
+
subject { DummyResource.new('http://example.org/test') }
|
36
|
+
let(:license) { DummyLicense.new }
|
37
|
+
|
38
|
+
xit 'should output a valid jsonld representation of itself' do
|
39
|
+
g = RDF::Graph.new << JSON::LD::API.toRdf(subject.as_jsonld)
|
40
|
+
expect(subject == g).to be true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should have contexts' do
|
44
|
+
expect(subject.as_jsonld['@context'].keys).to eq ["license", "title"]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should use context with dump' do
|
48
|
+
context = JSON.parse(subject.dump :jsonld)['@context']
|
49
|
+
subject.class.properties.keys.each do |prop|
|
50
|
+
expect(context).to include prop
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|