rdf-ldp 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 608eab3122c07390b9ea22a578ab0744fe18fe02
4
- data.tar.gz: ddcd8b00538a683ef78f4cbda395573cebacdc23
3
+ metadata.gz: 5a633f094bb28ab5b2fc03dec3fbfdf5e0735a0c
4
+ data.tar.gz: 61979520bcc04f1966a46eb9ee41f250e7c80128
5
5
  SHA512:
6
- metadata.gz: 29b2ba9c4f2f3baab28bc2d554f5e782cc3756fad291e277486c393e54166a11ccd3ce331c1de11c46849da36548df9ba3a092abbd8424989ee98e9bfb77a57d
7
- data.tar.gz: 2e52d0ea153620570b1be88497ff0edb1be04ac860715280e69c9389d01361614c8a39b7d26337007985a8b13d97f546a4d4384fa90f7eb850c5c3e49100aa55
6
+ metadata.gz: c9e086f88098b88693e86f90ccef8b1e35c123c2b4122cf4f4cc1a3d14db744ae77fe5bf7d6ad8f3bfadec3e026723bf60b488cc91fb64cb7bc586bfc1a3d0aa
7
+ data.tar.gz: e245c4c5bf3d764dfb5c67e9cef1d9e0820adecec5c93c461a73c923c9ddee690ed99cb4c7ffd5a25c8fd5046bd1ff7102e00911a02bee1855256c52bc473022
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.9.3
2
+ -----
3
+ - Expose shared examples for LDP interaction models in
4
+ `lib/rdf/ldp/spec`.
5
+
1
6
  0.9.2
2
7
  -----
3
8
  - Reduce memory allocation for URIs by using `RDF::URI#intern`.
data/README.md CHANGED
@@ -103,6 +103,40 @@ And run your server with:
103
103
  $ rackup
104
104
  ```
105
105
 
106
+ Testing
107
+ -------
108
+
109
+ RSpec shared examples for the required behaviors of LDP resource and container
110
+ types are included in `rdf/ldp/spec` for use in customized implementations.
111
+ Running these example sets will help ensure LDP compliance for specialized
112
+ resource behaviors.
113
+
114
+ This test suite is provided provisionally and may be incomplete or overly
115
+ strict. Please [report issues](https://github.com/ruby-rdf/rdf-ldp/issues)
116
+ encountered during its use.
117
+
118
+ ```ruby
119
+ require 'rdf/ldp/spec'
120
+
121
+ describe MyResource do
122
+ it_behaves_like 'a Resource'
123
+ end
124
+
125
+ describe MyRDFSource do
126
+ it_behaves_like 'an RDFSource'
127
+ end
128
+
129
+ # ...
130
+
131
+ describe MyIndirectContainer do
132
+ it_behaves_like 'an IndirectContainer'
133
+ end
134
+ ```
135
+
136
+ We recommend running the official
137
+ [LDP testsuite](https://github.com/cbeer/ldp_testsuite_wrapper), as integration
138
+ tests in addition to the above examples.
139
+
106
140
  Compliance
107
141
  ----------
108
142
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.2
1
+ 0.9.3
data/app/lamprey.rb CHANGED
@@ -1,54 +1,133 @@
1
1
  require 'rack/ldp'
2
2
  require 'sinatra/base'
3
3
 
4
- class RDF::Lamprey < Sinatra::Base
5
- use Rack::Lint
6
- use Rack::LDP::ContentNegotiation
7
- use Rack::LDP::Errors
8
- use Rack::LDP::Responses
9
- use Rack::ConditionalGet
10
- use Rack::LDP::Requests
11
-
12
- # Set defaults in case user has not configured values
13
- configure do
14
- set :repository, RDF::Repository.new
15
- end
4
+ module RDF
5
+ ##
6
+ # A basic implementation of an LDP Server.
7
+ class Lamprey < Sinatra::Base
8
+ use Rack::Lint
9
+ use Rack::LDP::ContentNegotiation
10
+ use Rack::LDP::Errors
11
+ use Rack::LDP::Responses
12
+ use Rack::ConditionalGet
13
+ use Rack::LDP::Requests
16
14
 
17
- get '/*' do
18
- RDF::LDP::Container.new(RDF::URI(request.url), settings.repository)
19
- .create(StringIO.new, 'text/turtle') if settings.repository.empty?
20
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
21
- end
15
+ get '/*' do
16
+ if settings.repository.empty?
17
+ RDF::LDP::Container
18
+ .new(RDF::URI(request.url), settings.repository)
19
+ .create(StringIO.new, 'text/turtle')
20
+ end
22
21
 
23
- patch '/*' do
24
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
25
- end
22
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
23
+ end
26
24
 
27
- post '/*' do
28
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
29
- end
25
+ patch '/*' do
26
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
27
+ end
30
28
 
31
- put '/*' do
32
- begin
29
+ post '/*' do
33
30
  RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
34
- rescue RDF::LDP::NotFound
35
- model = request.env.fetch('HTTP_LINK', '')
36
- RDF::LDP::Resource.interaction_model(model)
37
- .new(RDF::URI(request.url), settings.repository)
38
31
  end
39
- end
40
32
 
41
- options '/*' do
42
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
43
- end
33
+ put '/*' do
34
+ begin
35
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
36
+ rescue RDF::LDP::NotFound
37
+ model = request.env.fetch('HTTP_LINK', '')
44
38
 
45
- head '/*' do
46
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
47
- end
39
+ RDF::LDP::Resource
40
+ .interaction_model(model)
41
+ .new(RDF::URI(request.url), settings.repository)
42
+ end
43
+ end
48
44
 
49
- delete '/*' do
50
- RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
51
- end
45
+ options '/*' do
46
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
47
+ end
48
+
49
+ head '/*' do
50
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
51
+ end
52
+
53
+ delete '/*' do
54
+ RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
55
+ end
56
+
57
+ ##
58
+ # @example Configuring Lamprey server
59
+ # Lamprey::Config
60
+ # .register_repository!(:my_repo, RDF::Repository)
61
+ #
62
+ # Lamprey::Config.configure!(repository: :my_repo)
63
+ class Config
64
+ ##
65
+ # @see #new
66
+ # @see #configure!
67
+ def self.configure!(**options)
68
+ new(**options).configure!
69
+ end
70
+
71
+ ##
72
+ # Registers a repository for use with the {#build_repository} method.
73
+ #
74
+ # @example Registering a custom repository
75
+ # MyRepository = Class.new(RDF::Repository)
76
+ #
77
+ # Lamprey::Config.register_repository!(:my_repo, MyRepository)
78
+ #
79
+ # @param name [Symbol]
80
+ # @param klass [Class]
81
+ # @return [void]
82
+ def self.register_repository!(name, klass)
83
+ @@repositories[name] = klass
84
+ end
85
+
86
+ ##
87
+ # @!attribute [rw] options
88
+ attr_accessor :options
52
89
 
53
- run! if app_file == $0
90
+ @@repositories = { default: RDF::Repository }
91
+
92
+ ##
93
+ # @param repository [RDF::Repository]
94
+ def initialize(repository: :default)
95
+ @options = {}
96
+ @options[:repository] = repository
97
+ end
98
+
99
+ ##
100
+ # Builds the repository as given in the configuration.
101
+ #
102
+ # @return [RDF::Repository] a repository instance
103
+ def build_repository
104
+ @@repositories.fetch(options[:repository]) do
105
+ warn "#{options[:repository]} is not a configured repository. Use "\
106
+ '`Lamprey::Config.register_repository!` to register it before '\
107
+ 'configuration. Falling back on the default: ' \
108
+ "#{@@repositories[:default]}."
109
+ @@repositories[:default]
110
+ end.new
111
+ end
112
+
113
+ ##
114
+ # Configures {RDF::Lamprey} with {#options}.
115
+ #
116
+ # @return [void]
117
+ def configure!
118
+ repository = build_repository
119
+ unless repository.persistent?
120
+ warn "#{repository} is not a persistent repository. "\
121
+ 'Data will be lost on server shutdown.'
122
+ end
123
+
124
+ RDF::Lamprey.configure { |config| config.set :repository, repository }
125
+ end
126
+ end
127
+
128
+ # Set defaults in case user does not configure values
129
+ Config.configure!
130
+
131
+ run! if app_file == $PROGRAM_NAME
132
+ end
54
133
  end
data/bin/lamprey CHANGED
@@ -1,5 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'app')))
2
+ $LOAD_PATH
3
+ .unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'app')))
3
4
  require 'lamprey'
5
+ require 'optparse'
6
+
7
+ options = {}
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = 'Usage: lamprey [options]'
11
+
12
+ opts.on('-rREPO', '--repository=REPO', 'Set the repository') do |repo|
13
+ options[:repository] = repo.to_sym
14
+ end
15
+ end.parse!
16
+
17
+ RDF::Lamprey::Config.configure!(**options)
4
18
 
5
19
  RDF::Lamprey.run!
data/lib/rack/ldp.rb CHANGED
@@ -14,15 +14,15 @@ module Rack
14
14
  # Provides Rack middleware for handling Linked Data Platform requirements
15
15
  # when passed {RDF::LDP::Resource} and its subclasses as response objects.
16
16
  #
17
- # Response objects that are not an {RDF::LDP::Resource} are passed over
17
+ # Response objects that are not an {RDF::LDP::Resource} are passed over
18
18
  # without alteration, allowing server implementers to mix LDP interaction
19
19
  # patterns with others on the same server.
20
20
  #
21
- # The suite can be mix-and-matched as needed. This allows easy swap in of
21
+ # The suite can be mix-and-matched as needed. This allows easy swap in of
22
22
  # custom handlers for parts of the behavior. It is recommended that you use
23
23
  # {Rack::LDP::ContentNegotiation}, {Rack::LDP::Errors}, {Rack::LDP::Responses}
24
- # and {Rack::LDP::Reousets} as the outer middleware layers. With these in
25
- # place, you can handle requests as needed in your application, giving
24
+ # and {Rack::LDP::Reousets} as the outer middleware layers. With these in
25
+ # place, you can handle requests as needed in your application, giving
26
26
  # responses conforming to the core {RDF::LDP::Resource} interface.
27
27
  #
28
28
  # @example
@@ -33,7 +33,7 @@ module Rack
33
33
  # use Rack::LDP::Requests
34
34
  # # ...
35
35
  # end
36
- #
36
+ #
37
37
  # @see http://www.w3.org/TR/ldp/ the LDP specification
38
38
  module LDP
39
39
  ##
@@ -46,17 +46,15 @@ module Rack
46
46
  end
47
47
 
48
48
  ##
49
- # Catches {RDF::LDP::RequestError} and its various subclasses, building an
50
- # appropriate response
49
+ # Catches {RDF::LDP::RequestError} and its various subclasses, building an
50
+ # appropriate response
51
51
  #
52
52
  # @param [Array] env a rack env array
53
53
  # @return [Array] a rack env array with added headers
54
54
  def call(env)
55
- begin
56
- @app.call(env)
57
- rescue RDF::LDP::RequestError => err
58
- return [err.status, err.headers, [err.message]]
59
- end
55
+ @app.call(env)
56
+ rescue RDF::LDP::RequestError => err
57
+ return [err.status, err.headers, [err.message]]
60
58
  end
61
59
  end
62
60
 
@@ -94,7 +92,7 @@ module Rack
94
92
  end
95
93
 
96
94
  ##
97
- # Handles a Rack protocol request. Sends appropriate request to the
95
+ # Handles a Rack protocol request. Sends appropriate request to the
98
96
  # object, alters response accordingly.
99
97
  #
100
98
  # @param [Array] env a rack env array
@@ -103,19 +101,19 @@ module Rack
103
101
  status, headers, response = @app.call(env)
104
102
  return [status, headers, response] unless
105
103
  response.is_a? RDF::LDP::Resource
106
-
104
+
107
105
  response
108
106
  .send(:request, env['REQUEST_METHOD'].to_sym, status, headers, env)
109
107
  end
110
108
  end
111
109
 
112
110
  ##
113
- # Specializes {Rack::LinkedData::ContentNegotiation}, making the default
111
+ # Specializes {Rack::LinkedData::ContentNegotiation}, making the default
114
112
  # return type 'text/turtle'.
115
113
  #
116
114
  # @see Rack::LinkedData::ContentNegotiation}, making
117
115
  class ContentNegotiation < Rack::LinkedData::ContentNegotiation
118
- DEFAULT_PREFIXES =
116
+ DEFAULT_PREFIXES =
119
117
  Hash[*RDF::Vocabulary.map { |v| [v.__prefix__, v.to_uri] }.flatten]
120
118
  .freeze
121
119
 
@@ -126,13 +124,13 @@ module Rack
126
124
  end
127
125
 
128
126
  ##
129
- # The default LinkedData Conneg doesn't support wildcard operators. We
130
- # patch in support for 'text/*' manually, giving Turtle. This should be
127
+ # The default LinkedData Conneg doesn't support wildcard operators. We
128
+ # patch in support for 'text/*' manually, giving Turtle. This should be
131
129
  # considered helpful by LDP clients.
132
- #
130
+ #
133
131
  # @see Rack::LinkedData::ContentNegotiation#find_writer_for_content_type
134
132
  def find_writer_for_content_type(content_type)
135
- return [RDF::Writer.for(:ttl), 'text/turtle'] if
133
+ return [RDF::Writer.for(:ttl), 'text/turtle'] if
136
134
  content_type == 'text/*'
137
135
  super
138
136
  end
data/lib/rdf/ldp.rb CHANGED
@@ -22,11 +22,12 @@ module RDF
22
22
  # @see http://www.w3.org/TR/ldp/ for the Linked Data platform specification
23
23
  module LDP
24
24
  InteractionModel.register(RDF::LDP::RDFSource, default: true)
25
- InteractionModel.register(RDF::LDP::Container, for: RDF::Vocab::LDP.BasicContainer)
25
+ InteractionModel.register(RDF::LDP::Container,
26
+ for: RDF::Vocab::LDP.BasicContainer)
26
27
  InteractionModel.register(RDF::LDP::DirectContainer)
27
28
  InteractionModel.register(RDF::LDP::IndirectContainer)
28
29
  InteractionModel.register(RDF::LDP::NonRDFSource)
29
-
30
+
30
31
  CONTAINER_CLASSES = {
31
32
  basic: RDF::Vocab::LDP.BasicContainer.freeze,
32
33
  direct: RDF::LDP::DirectContainer.to_uri.freeze,
@@ -82,8 +82,8 @@ module RDF::LDP
82
82
  # membership triples as appropriate for the container type.
83
83
  #
84
84
  # If a transaction is passed as the second argument, the removal of the
85
- # containment triple is completed when the transaction closes; otherwise it is
86
- # handled atomically.
85
+ # containment triple is completed when the transaction closes; otherwise it
86
+ # is handled atomically.
87
87
  #
88
88
  # @param [RDF::Term] a new member for this container
89
89
  # @param transaction [RDF::Transaction] an active transaction as context for
@@ -157,7 +157,7 @@ module RDF::LDP
157
157
 
158
158
  raise UnsupportedMediaType unless method
159
159
 
160
- temp_data = RDF::Repository.new << graph.statements
160
+ temp_data = RDF::Repository.new << graph.statements
161
161
  temp_graph = RDF::Graph.new(graph_name: graph.name, data: temp_data)
162
162
  send(method, env['rack.input'], temp_graph)
163
163
 
@@ -204,14 +204,18 @@ module RDF::LDP
204
204
  predicate: CONTAINS_URI)
205
205
 
206
206
  tx_containment.each do |statement|
207
- raise(Conflict, 'Attempted to write unacceptable LDP ' \
208
- "containment-triple: #{statement}") unless
209
- existing_triples.include?(statement)
207
+ unless existing_triples.include?(statement)
208
+ raise(Conflict, 'Attempted to write unacceptable LDP ' \
209
+ "containment-triple: #{statement}")
210
+ end
210
211
  end
211
212
 
212
213
  deletes = existing_triples.reject { |st| tx_containment.include?(st) }
214
+
215
+ return if deletes.empty?
216
+
213
217
  raise(Conflict, 'Cannot remove containment triples in updates. ' \
214
- "Attepted to remove #{deletes}") unless deletes.empty?
218
+ "Attepted to remove #{deletes}")
215
219
  end
216
220
 
217
221
  ##
@@ -224,9 +228,11 @@ module RDF::LDP
224
228
  "containment-triple: #{st}")
225
229
  end
226
230
  end
231
+
232
+ return if existing_triples.empty?
233
+
227
234
  raise(Conflict, 'Cannot remove containment triples in updates. ' \
228
- "Attepted to remove #{existing_triples}") unless
229
- existing_triples.empty?
235
+ "Attepted to remove #{existing_triples}")
230
236
  end
231
237
  end
232
238
  end
@@ -65,7 +65,8 @@ module RDF::LDP
65
65
  #
66
66
  # @see RDF::LDP::Container#add
67
67
  def add(resource, transaction = nil)
68
- process_membership_resource(resource, transaction) do |container, quad, subject|
68
+ process_membership_resource(resource,
69
+ transaction) do |container, quad, subject|
69
70
  super(subject, transaction) # super handles nil transaction case
70
71
  target = transaction || container.graph
71
72
  target.insert(quad)
@@ -79,7 +80,8 @@ module RDF::LDP
79
80
  #
80
81
  # @see RDF::LDP::Container#remove
81
82
  def remove(resource, transaction = nil)
82
- process_membership_resource(resource, transaction) do |container, quad, subject|
83
+ process_membership_resource(resource,
84
+ transaction) do |container, quad, subject|
83
85
  super(subject, transaction) # super handles nil transaction case
84
86
  target = transaction || container.graph
85
87
  target.delete(quad)
@@ -156,7 +158,7 @@ module RDF::LDP
156
158
  resource
157
159
  end
158
160
 
159
- def process_membership_resource(resource, transaction = nil, member = nil)
161
+ def process_membership_resource(resource, _transaction = nil, member = nil)
160
162
  membership_triple = make_membership_triple((member || resource).to_uri)
161
163
 
162
164
  membership_triple.graph_name = subject_uri