ldp 0.6.4 → 1.0.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 +5 -5
- data/.circleci/config.yml +84 -0
- data/.github_changelog_generator +2 -0
- data/.rubocop.yml +34 -0
- data/.rubocop_todo.yml +264 -0
- data/CHANGELOG.md +308 -0
- data/CODE_OF_CONDUCT.md +36 -0
- data/CONTRIBUTING.md +23 -21
- data/Gemfile +10 -2
- data/LICENSE.txt +3 -1
- data/README.md +48 -15
- data/Rakefile +1 -1
- data/SUPPORT.md +5 -0
- data/bin/ldp +3 -5
- data/ldp.gemspec +4 -1
- data/lib/ldp/client.rb +8 -9
- data/lib/ldp/client/methods.rb +22 -22
- data/lib/ldp/client/prefer_headers.rb +6 -6
- data/lib/ldp/error.rb +1 -1
- data/lib/ldp/orm.rb +0 -1
- data/lib/ldp/resource.rb +4 -5
- data/lib/ldp/resource/binary_source.rb +7 -2
- data/lib/ldp/resource/rdf_source.rb +48 -46
- data/lib/ldp/response.rb +17 -7
- data/lib/ldp/version.rb +1 -1
- data/spec/lib/ldp/resource/binary_source_spec.rb +23 -6
- data/spec/lib/ldp/resource/rdf_source_spec.rb +2 -1
- data/spec/lib/ldp/response_spec.rb +6 -2
- metadata +54 -7
- data/.travis.yml +0 -14
data/lib/ldp/orm.rb
CHANGED
data/lib/ldp/resource.rb
CHANGED
@@ -6,7 +6,7 @@ module Ldp
|
|
6
6
|
attr_reader :client, :subject
|
7
7
|
attr_accessor :content
|
8
8
|
|
9
|
-
def self.for(client, subject, response
|
9
|
+
def self.for(client, subject, response)
|
10
10
|
case
|
11
11
|
when response.container?
|
12
12
|
Ldp::Container.for client, subject, response
|
@@ -57,8 +57,8 @@ module Ldp
|
|
57
57
|
def head
|
58
58
|
@head ||= begin
|
59
59
|
@get || client.head(subject)
|
60
|
-
|
61
|
-
|
60
|
+
rescue Ldp::NotFound
|
61
|
+
None
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -79,7 +79,7 @@ module Ldp
|
|
79
79
|
# @return [RdfSource] the new representation
|
80
80
|
# @raise [Ldp::Conflict] if you attempt to call create on an existing resource
|
81
81
|
def create &block
|
82
|
-
raise Ldp::Conflict, "Can't call create on an existing resource" unless new?
|
82
|
+
raise Ldp::Conflict, "Can't call create on an existing resource (#{subject})" unless new?
|
83
83
|
verb = subject.nil? ? :post : :put
|
84
84
|
resp = client.send(verb, (subject || @base_path), content) do |req|
|
85
85
|
req.headers["Link"] = "<#{interaction_model}>;rel=\"type\"" if interaction_model
|
@@ -130,6 +130,5 @@ module Ldp
|
|
130
130
|
def interaction_model
|
131
131
|
nil
|
132
132
|
end
|
133
|
-
|
134
133
|
end
|
135
134
|
end
|
@@ -2,16 +2,21 @@ module Ldp
|
|
2
2
|
class Resource::BinarySource < Ldp::Resource
|
3
3
|
attr_accessor :content
|
4
4
|
|
5
|
+
# @param client [Ldp::Client]
|
6
|
+
# @param subject [String] the URI for the resource
|
7
|
+
# @param content_or_response [String,Ldp::Response]
|
8
|
+
# @param base_path [String] ('')
|
5
9
|
def initialize client, subject, content_or_response = nil, base_path = ''
|
6
10
|
super
|
7
11
|
|
8
12
|
case content_or_response
|
9
|
-
when
|
13
|
+
when Ldp::Response
|
10
14
|
else
|
11
15
|
@content = content_or_response
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
19
|
+
# @return [Ldp::Response]
|
15
20
|
def content
|
16
21
|
@content ||= get.body
|
17
22
|
end
|
@@ -25,7 +30,7 @@ module Ldp
|
|
25
30
|
# Override inspect so that `content` is never shown. It is typically too big to be helpful
|
26
31
|
def inspect
|
27
32
|
string = "#<#{self.class.name}:#{self.object_id} "
|
28
|
-
fields = [:subject].map{|field| "#{field}=\"#{self.send(field)}\""}
|
33
|
+
fields = [:subject].map { |field| "#{field}=\"#{self.send(field)}\"" }
|
29
34
|
string << fields.join(", ") << ">"
|
30
35
|
end
|
31
36
|
|
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'rdf/turtle'
|
2
2
|
module Ldp
|
3
3
|
class Resource::RdfSource < Ldp::Resource
|
4
|
-
|
5
4
|
def initialize client, subject, graph_or_response = nil, base_path = ''
|
6
5
|
super
|
7
6
|
|
8
7
|
case graph_or_response
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
when RDF::Enumerable
|
9
|
+
@graph = graph_or_response
|
10
|
+
when Ldp::Response
|
11
|
+
when NilClass
|
12
|
+
# nop
|
13
|
+
else
|
14
|
+
raise ArgumentError, "Third argument to #{self.class}.new should be a RDF::Enumerable or a Ldp::Response. You provided #{graph_or_response.class}"
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
@@ -27,7 +26,17 @@ module Ldp
|
|
27
26
|
end
|
28
27
|
|
29
28
|
def graph
|
30
|
-
@graph ||=
|
29
|
+
@graph ||= begin
|
30
|
+
if subject.nil?
|
31
|
+
build_empty_graph
|
32
|
+
else
|
33
|
+
filtered_graph(response_graph)
|
34
|
+
end
|
35
|
+
rescue Ldp::NotFound
|
36
|
+
# This is an optimization that lets us avoid doing HEAD + GET
|
37
|
+
# when the object exists. We just need to handle the 404 case
|
38
|
+
build_empty_graph
|
39
|
+
end
|
31
40
|
end
|
32
41
|
|
33
42
|
def build_empty_graph
|
@@ -49,14 +58,6 @@ module Ldp
|
|
49
58
|
@response_graph ||= response_as_graph(get)
|
50
59
|
end
|
51
60
|
|
52
|
-
# Get the body and ensure it's UTF-8 encoded. Since Fedora 9.3 isn't
|
53
|
-
# returning a charset, then Net::HTTP is just returning ASCII-8BIT
|
54
|
-
# See https://github.com/ruby-rdf/rdf-turtle/issues/13
|
55
|
-
# See https://jira.duraspace.org/browse/FCREPO-1750
|
56
|
-
def body
|
57
|
-
body.force_encoding('utf-8')
|
58
|
-
end
|
59
|
-
|
60
61
|
protected
|
61
62
|
|
62
63
|
def interaction_model
|
@@ -64,41 +65,42 @@ module Ldp
|
|
64
65
|
end
|
65
66
|
|
66
67
|
private
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
graph
|
68
|
+
|
69
|
+
##
|
70
|
+
# @param [Faraday::Response] graph query response
|
71
|
+
# @return [RDF::Graph]
|
72
|
+
def response_as_graph(resp)
|
73
|
+
graph = build_empty_graph
|
74
|
+
resp.each_statement do |stmt|
|
75
|
+
graph << stmt
|
76
76
|
end
|
77
|
+
graph
|
78
|
+
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
80
|
+
##
|
81
|
+
# @param [RDF::Graph] original_graph The graph returned by the LDP server
|
82
|
+
# @return [RDF::Graph] A graph stripped of any inlined resources present in the original
|
83
|
+
def filtered_graph(original_graph)
|
84
|
+
inlined_resources = original_graph.query(predicate: RDF::Vocab::LDP.contains).map { |x| x.object }
|
85
|
+
|
86
|
+
# we want to scope this graph to just statements about this model, not contained relations
|
87
|
+
if inlined_resources.empty?
|
88
|
+
original_graph
|
89
|
+
else
|
90
|
+
graph_without_inlined_resources(original_graph, inlined_resources)
|
90
91
|
end
|
92
|
+
end
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
+
def graph_without_inlined_resources(original_graph, inlined_resources)
|
95
|
+
new_graph = build_empty_graph
|
94
96
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
97
|
+
original_graph.each_statement do |s|
|
98
|
+
unless inlined_resources.include? s.subject
|
99
|
+
new_graph << s
|
99
100
|
end
|
100
|
-
|
101
|
-
new_graph
|
102
101
|
end
|
102
|
+
|
103
|
+
new_graph
|
104
|
+
end
|
103
105
|
end
|
104
106
|
end
|
data/lib/ldp/response.rb
CHANGED
@@ -10,6 +10,7 @@ module Ldp
|
|
10
10
|
|
11
11
|
attr_writer :etag, :last_modified
|
12
12
|
|
13
|
+
# @param response [Faraday::Response]
|
13
14
|
def initialize(response)
|
14
15
|
@response = response
|
15
16
|
end
|
@@ -78,10 +79,10 @@ module Ldp
|
|
78
79
|
# Get the subject for the response
|
79
80
|
def subject
|
80
81
|
@subject ||= if has_page?
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
graph.first_object [page_subject, RDF::Vocab::LDP.pageOf, nil]
|
83
|
+
else
|
84
|
+
page_subject
|
85
|
+
end
|
85
86
|
end
|
86
87
|
|
87
88
|
##
|
@@ -154,7 +155,7 @@ module Ldp
|
|
154
155
|
# Statements about the page
|
155
156
|
def page
|
156
157
|
@page_graph ||= begin
|
157
|
-
g = RDF::Graph.new
|
158
|
+
g = RDF::Graph.new
|
158
159
|
|
159
160
|
if resource?
|
160
161
|
res = graph.query RDF::Statement.new(page_subject, nil, nil)
|
@@ -199,12 +200,21 @@ module Ldp
|
|
199
200
|
end
|
200
201
|
|
201
202
|
def content_disposition_filename
|
202
|
-
|
203
|
-
URI.decode(
|
203
|
+
filename = content_disposition_attributes['filename']
|
204
|
+
URI.decode(filename) if filename
|
204
205
|
end
|
205
206
|
|
206
207
|
private
|
207
208
|
|
209
|
+
def content_disposition_attributes
|
210
|
+
parts = headers['Content-Disposition'].split(/;\s*/).collect { |entry| entry.split(/\s*=\s*/) }
|
211
|
+
entries = parts.collect do |part|
|
212
|
+
value = part[1].respond_to?(:sub) ? part[1].sub(%r{^"(.*)"$}, '\1') : part[1]
|
213
|
+
[part[0], value]
|
214
|
+
end
|
215
|
+
Hash[entries]
|
216
|
+
end
|
217
|
+
|
208
218
|
def headers
|
209
219
|
response.headers
|
210
220
|
end
|
data/lib/ldp/version.rb
CHANGED
@@ -4,21 +4,26 @@ describe Ldp::Resource::BinarySource do
|
|
4
4
|
let(:client) { instance_double(Ldp::Client) }
|
5
5
|
let(:uri) { 'http://example.com/foo/bar' }
|
6
6
|
let(:content) { 'somecontent' }
|
7
|
-
|
7
|
+
let(:instance) { described_class.new(client, uri, content) }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
describe "#inspect" do
|
10
|
+
subject { instance.inspect }
|
11
|
+
|
12
|
+
it "does not display content" do
|
13
|
+
expect(subject).to match /subject=\"http:\/\/example\.com\/foo\/bar\"/
|
14
|
+
expect(subject).not_to match /somecontent/
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
describe '#described_by' do
|
19
|
+
subject { instance.described_by }
|
15
20
|
context 'without a description' do
|
16
21
|
before do
|
17
22
|
allow(client).to receive(:head).and_return(instance_double(Ldp::Response, links: { }))
|
18
23
|
end
|
19
24
|
|
20
25
|
it 'retrieves the description object' do
|
21
|
-
expect(subject
|
26
|
+
expect(subject).to eq nil
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
@@ -31,8 +36,20 @@ describe Ldp::Resource::BinarySource do
|
|
31
36
|
let(:desc) { double }
|
32
37
|
|
33
38
|
it 'retrieves the description object' do
|
34
|
-
expect(subject
|
39
|
+
expect(subject).to eq desc
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|
43
|
+
|
44
|
+
describe "#content" do
|
45
|
+
context "when an Ldp::Response is passed in" do
|
46
|
+
let(:mock_response) { instance_double(Faraday::Response, headers: {}, env: { url: "info:a" }) }
|
47
|
+
let(:content) { Ldp::Response.new(mock_response) }
|
48
|
+
let(:client) { instance_double(Ldp::Client, get: double(body: 'retrieved value')) }
|
49
|
+
|
50
|
+
subject { instance.content }
|
51
|
+
|
52
|
+
it { is_expected.to eq 'retrieved value' }
|
53
|
+
end
|
54
|
+
end
|
38
55
|
end
|
@@ -17,6 +17,7 @@ describe Ldp::Resource::RdfSource do
|
|
17
17
|
stub.post("/") { [201]}
|
18
18
|
stub.put("/abs_url_object") { [201]}
|
19
19
|
stub.head("/abs_url_object") {[404]}
|
20
|
+
stub.get("/abs_url_object") {[404]}
|
20
21
|
stub.head("/existing_object") {[200, {'Content-Type'=>'text/turtle'}]}
|
21
22
|
stub.get("/existing_object") {[200, {'Content-Type'=>'text/turtle'}, simple_graph_source]}
|
22
23
|
end
|
@@ -102,7 +103,7 @@ describe Ldp::Resource::RdfSource do
|
|
102
103
|
end
|
103
104
|
context 'for an existing object' do
|
104
105
|
subject { Ldp::Resource::RdfSource.new mock_client, "http://my.ldp.server/existing_object" }
|
105
|
-
it do
|
106
|
+
it do
|
106
107
|
expect(subject.graph.size).to eql(1)
|
107
108
|
end
|
108
109
|
end
|
@@ -199,12 +199,16 @@ describe Ldp::Response do
|
|
199
199
|
describe '#content_disposition_filename' do
|
200
200
|
before do
|
201
201
|
allow(mock_response).to receive(:headers).and_return(
|
202
|
-
'Content-Disposition' => 'filename="xyz.txt";'
|
202
|
+
{ 'Content-Disposition' => 'filename="xyz.txt";' },
|
203
|
+
{ 'Content-Disposition' => 'attachment; filename=xyz.txt' },
|
204
|
+
{ 'Content-Disposition' => 'attachment; filename="xyz.txt"; size="12345"' },
|
205
|
+
{ 'Content-Disposition' => 'attachment; filename=""; size="12345"' },
|
203
206
|
)
|
204
207
|
end
|
205
208
|
|
206
209
|
it 'provides the filename from the content disposition header' do
|
207
|
-
expect(subject.content_disposition_filename).to eq 'xyz.txt'
|
210
|
+
3.times { expect(subject.content_disposition_filename).to eq 'xyz.txt' }
|
211
|
+
expect(subject.content_disposition_filename).to eq ''
|
208
212
|
end
|
209
213
|
end
|
210
214
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ldp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Beer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
145
|
+
version: '2.0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
152
|
+
version: '2.0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: rake
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,6 +206,48 @@ dependencies:
|
|
206
206
|
- - ">="
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: rspec_junit_formatter
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: bixby
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: 3.0.0
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - "~>"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: 3.0.0
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: github_changelog_generator
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
209
251
|
description: Linked Data Platform client library
|
210
252
|
email:
|
211
253
|
- chris@cbeer.info
|
@@ -214,13 +256,19 @@ executables:
|
|
214
256
|
extensions: []
|
215
257
|
extra_rdoc_files: []
|
216
258
|
files:
|
259
|
+
- ".circleci/config.yml"
|
260
|
+
- ".github_changelog_generator"
|
217
261
|
- ".gitignore"
|
218
|
-
- ".
|
262
|
+
- ".rubocop.yml"
|
263
|
+
- ".rubocop_todo.yml"
|
264
|
+
- CHANGELOG.md
|
265
|
+
- CODE_OF_CONDUCT.md
|
219
266
|
- CONTRIBUTING.md
|
220
267
|
- Gemfile
|
221
268
|
- LICENSE.txt
|
222
269
|
- README.md
|
223
270
|
- Rakefile
|
271
|
+
- SUPPORT.md
|
224
272
|
- bin/ldp
|
225
273
|
- ldp.gemspec
|
226
274
|
- lib/ldp.rb
|
@@ -267,8 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
315
|
- !ruby/object:Gem::Version
|
268
316
|
version: '0'
|
269
317
|
requirements: []
|
270
|
-
|
271
|
-
rubygems_version: 2.6.8
|
318
|
+
rubygems_version: 3.1.2
|
272
319
|
signing_key:
|
273
320
|
specification_version: 4
|
274
321
|
summary: Linked Data Platform client library
|