ldp 0.6.4 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|