rdf-ldp 0.7.0 → 0.8.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6984fe1fabab30524697db0471c39721f68fb54
4
- data.tar.gz: fc3b6d95051b4c82b02cb9d474a379b15e5584d0
3
+ metadata.gz: 663f6cdf86d6e9ead88bd25c120ca190bb6e5b6a
4
+ data.tar.gz: 3dee66e41f42baff2923e2ba8977b54673d31220
5
5
  SHA512:
6
- metadata.gz: 0243e142e3b59232c19360ad4b507dda9e32ea9643e794318fb5227fe653261b64a61b82e655620976a05fec535f35193c5c7fccb225ed65669ff07192875693
7
- data.tar.gz: 7256e7bb1c2c2a59c16e64def71c9101e5cd1b071d6f2432564d1dfb3d8feb559732b85821a3e0a71773f15f69cab5d8ee1da9e36af3dc1d4ee3b29793d89811
6
+ metadata.gz: ba4698c28103ce63f83eeb8992116e5258529cd04eac8fa5e5dfae223cb1843e4e465645023b28ba6ed37ccad386c2aa55ec9de984d6b1879c484bf2db44dcbe
7
+ data.tar.gz: 6a4c62830de24ffc8428373db0ba5d3badbb9fbce6f66c6e1d45a9de827f9bc5259c54df44cc1ebac61acd49a460c9c2e5e14cb00282dfabf0c8533caa9f1a92
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ 0.8.0
2
+ -----
3
+ - Deletes on NonRDFSources now leave the file on disk if deleting the
4
+ metadata fails, making deletes atomic from the client's perspective.
5
+ - Changes the NonRDFSource interface to allow configuration of storage
6
+ adapters via dependency injection.
7
+ - Ends support for Ruby versions earlier than 2.2.2.
8
+
1
9
  0.7.0
2
10
  -----
3
11
  - Changes handling of input streams to be compliant with Rack. Allows
data/README.md CHANGED
@@ -82,7 +82,7 @@ use Rack::LDP::Requests
82
82
  #
83
83
  repository = RDF::Repository.new
84
84
  RDF::LDP::Container.new(RDF::URI('http://localhost:9292/'), repository)
85
- .create('', 'text/plain') if repository.empty?
85
+ .create(StringIO.new(''), 'text/plain') if repository.empty?
86
86
 
87
87
  app = proc do |env|
88
88
  # Return a Rack response, giving an `RDF::LDP::Resource`-like object as the body.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
data/lib/rdf/ldp.rb CHANGED
@@ -13,15 +13,15 @@ require 'rdf/ldp/indirect_container'
13
13
  module RDF
14
14
  ##
15
15
  # This module implements a basic domain model for Linked Data Platform (LDP).
16
- # Its classes allow CRUD operations on LDP RDFSources, NonRDFSources and
17
- # Containers, while presenting an interface appropriate for consumption by
16
+ # Its classes allow CRUD operations on LDP RDFSources, NonRDFSources and
17
+ # Containers, while presenting an interface appropriate for consumption by
18
18
  # Rack servers.
19
- #
19
+ #
20
20
  # @see RDF::LDP::Resource
21
21
  # @see http://www.w3.org/TR/ldp/ for the Linked Data platform specification
22
22
  module LDP
23
23
  ##
24
- # Interaction models are in reverse order of preference for POST/PUT
24
+ # Interaction models are in reverse order of preference for POST/PUT
25
25
  # requests; e.g. if a client sends a request with Resource, RDFSource, and
26
26
  # BasicContainer headers, the server gives a basic container.
27
27
  INTERACTION_MODELS = {
@@ -34,20 +34,20 @@ module RDF
34
34
  RDF::LDP::NonRDFSource.to_uri => RDF::LDP::NonRDFSource
35
35
  }.freeze
36
36
 
37
- CONTAINER_CLASSES = {
38
- basic: RDF::Vocab::LDP.BasicContainer,
39
- direct: RDF::LDP::DirectContainer.to_uri,
40
- indirect: RDF::LDP::IndirectContainer.to_uri
41
- }
37
+ CONTAINER_CLASSES = {
38
+ basic: RDF::Vocab::LDP.BasicContainer.freeze,
39
+ direct: RDF::LDP::DirectContainer.to_uri.freeze,
40
+ indirect: RDF::LDP::IndirectContainer.to_uri.freeze
41
+ }.freeze
42
42
 
43
- CONSTRAINED_BY = RDF::Vocab::LDP.constrainedBy
43
+ CONSTRAINED_BY = RDF::Vocab::LDP.constrainedBy.freeze
44
44
 
45
45
  ##
46
46
  # A base class for HTTP request errors.
47
47
  #
48
48
  # This and its subclasses are caught and handled by Rack::LDP middleware.
49
49
  # When a `RequestError` is caught by server middleware, its `#status` can be
50
- # used as a response code and `#headers` may be added to (or replace) the
50
+ # used as a response code and `#headers` may be added to (or replace) the
51
51
  # existing HTTP headers.
52
52
  class RequestError < RuntimeError
53
53
  STATUS = 500
@@ -57,7 +57,7 @@ module RDF
57
57
  end
58
58
 
59
59
  def headers
60
- uri =
60
+ uri =
61
61
  'https://github.com/no-reply/rdf-ldp/blob/master/CONSTRAINED_BY.md'
62
62
  { 'Link' => "<#{uri}>;rel=\"#{CONSTRAINED_BY}\"" }
63
63
  end
@@ -1,11 +1,11 @@
1
1
  module RDF::LDP
2
2
  ##
3
- # An LDP Basic Container. This also serves as a base class for other
3
+ # An LDP Basic Container. This also serves as a base class for other
4
4
  # container types. Containers are implemented as `RDF::LDP::RDFSources` with
5
5
  # the ability to contain other resources.
6
6
  #
7
7
  # Containers respond to `#post`, allowing new resources to be added to them.
8
- # On the public interface (not running through HTTP/`#request`), this is
8
+ # On the public interface (not running through HTTP/`#request`), this is
9
9
  # supported by `#add` and `#remove`.
10
10
  #
11
11
  # Containers will throw errors when attempting to edit them in conflict with
@@ -15,7 +15,7 @@ module RDF::LDP
15
15
  # of LDP Container
16
16
  class Container < RDFSource
17
17
  ##
18
- # @return [RDF::URI] uri with lexical representation
18
+ # @return [RDF::URI] uri with lexical representation
19
19
  # 'http://www.w3.org/ns/ldp#Container'
20
20
  def self.to_uri
21
21
  RDF::Vocab::LDP.Container
@@ -36,25 +36,25 @@ module RDF::LDP
36
36
  ##
37
37
  # Create with validation as required for the LDP container.
38
38
  #
39
- # @raise [RDF::LDP::Conflict] if the create inserts triples that are not
39
+ # @raise [RDF::LDP::Conflict] if the create inserts triples that are not
40
40
  # allowed by LDP for the container type
41
41
  # @see RDFSource#create
42
42
  def create(input, content_type, &block)
43
- super do |transaction|
43
+ super do |transaction|
44
44
  validate_triples!(transaction)
45
45
  yield transaction if block_given?
46
46
  end
47
47
  self
48
48
  end
49
-
49
+
50
50
  ##
51
51
  # Updates with validation as required for the LDP container.
52
52
  #
53
- # @raise [RDF::LDP::Conflict] if the update edits triples that are not
53
+ # @raise [RDF::LDP::Conflict] if the update edits triples that are not
54
54
  # allowed by LDP for the container type
55
55
  # @see RDFSource#update
56
56
  def update(input, content_type, &block)
57
- super do |transaction|
57
+ super do |transaction|
58
58
  validate_triples!(transaction)
59
59
  yield transaction if block_given?
60
60
  end
@@ -62,12 +62,12 @@ module RDF::LDP
62
62
  end
63
63
 
64
64
  ##
65
- # Adds a member `resource` to the container. Handles containment and
65
+ # Adds a member `resource` to the container. Handles containment and
66
66
  # membership triples as appropriate for the container type.
67
67
  #
68
- # If a transaction is passed as the second argument, the additon of the
69
- # containment triple is completed when the transaction closes; otherwise it is
70
- # handled atomically.
68
+ # If a transaction is passed as the second argument, the additon of the
69
+ # containment triple is completed when the transaction closes; otherwise it
70
+ # is handled atomically.
71
71
  #
72
72
  # @param [RDF::Term] a new member for this container
73
73
  # @param transaction [RDF::Transaction] an active transaction as context for
@@ -81,8 +81,8 @@ module RDF::LDP
81
81
  # Removes a member `resource` from the container. Handles containment and
82
82
  # membership triples as appropriate for the container type.
83
83
  #
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
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
86
  # handled atomically.
87
87
  #
88
88
  # @param [RDF::Term] a new member for this container
@@ -96,9 +96,7 @@ module RDF::LDP
96
96
  ##
97
97
  # @return [RDF::Query::Enumerator] the containment triples
98
98
  def containment_triples
99
- graph.query([subject_uri,
100
- RDF::Vocab::LDP.contains,
101
- nil]).statements
99
+ graph.query([subject_uri, CONTAINS_URI, nil]).statements
102
100
  end
103
101
 
104
102
  ##
@@ -106,7 +104,7 @@ module RDF::LDP
106
104
  #
107
105
  # @return [Boolean] true if the containment triple exists
108
106
  def has_containment_triple?(statement)
109
- !(containment_triples.find { |t| statement == t }.nil?)
107
+ !containment_triples.find { |t| statement == t }.nil?
110
108
  end
111
109
 
112
110
  ##
@@ -116,7 +114,7 @@ module RDF::LDP
116
114
  # the transaction's inserts; otherwise it is added directly to `#graph`.
117
115
  #
118
116
  # @param resource [RDF::Term] a new member for this container
119
- # @param transaction [RDF::Transaction]
117
+ # @param transaction [RDF::Transaction]
120
118
  # @return [Container] self
121
119
  def add_containment_triple(resource, transaction = nil)
122
120
  target = transaction || graph
@@ -132,7 +130,7 @@ module RDF::LDP
132
130
  # the transaction's deletes; otherwise it is deleted directly from `#graph`.
133
131
  #
134
132
  # @param resource [RDF::Term] a member to remove from this container
135
- # @param transaction [RDF::Transaction]
133
+ # @param transaction [RDF::Transaction]
136
134
  # @return [Container] self
137
135
  def remove_containment_triple(resource, transaction = nil)
138
136
  target = transaction || graph
@@ -144,16 +142,16 @@ module RDF::LDP
144
142
  ##
145
143
  # @param [RDF::Term] a member to be represented in the containment triple
146
144
  #
147
- # @return [RDF::URI] the containment triple, with a graph_name pointing
145
+ # @return [RDF::URI] the containment triple, with a graph_name pointing
148
146
  # to `#graph`
149
147
  def make_containment_triple(resource)
150
- RDF::Statement(subject_uri, RDF::Vocab::LDP.contains, resource,
148
+ RDF::Statement(subject_uri, CONTAINS_URI, resource,
151
149
  graph_name: subject_uri)
152
150
  end
153
151
 
154
152
  private
155
153
 
156
- def patch(status, headers, env)
154
+ def patch(_status, headers, env)
157
155
  check_precondition!(env)
158
156
  method = patch_types[env['CONTENT_TYPE']]
159
157
 
@@ -177,58 +175,57 @@ module RDF::LDP
177
175
  #
178
176
  # @raise [RDF::LDP::RequestError] when creation fails
179
177
  #
180
- # @return [Array<Fixnum, Hash<String, String>, #each] a new Rack response
178
+ # @return [Array<Fixnum, Hash<String, String>, #each] a new Rack response
181
179
  # array.
182
- def post(status, headers, env)
180
+ def post(_status, headers, env)
183
181
  klass = self.class.interaction_model(env.fetch('HTTP_LINK', ''))
184
182
  slug = env['HTTP_SLUG']
185
183
  slug = klass.gen_id if slug.nil? || slug.empty?
186
- raise NotAcceptable.new('Refusing to create resource with `#` in Slug') if
184
+ raise(NotAcceptable, 'Refusing to create resource with `#` in Slug') if
187
185
  slug.include? '#'
188
186
 
189
187
  id = (subject_uri / slug).canonicalize
190
188
 
191
189
  created = klass.new(id, @data)
192
-
190
+
193
191
  created.create(env['rack.input'], env['CONTENT_TYPE']) do |transaction|
194
192
  add(created, transaction)
195
193
  end
196
-
194
+
197
195
  headers['Location'] = created.subject_uri.to_s
198
196
  [201, created.send(:update_headers, headers), created]
199
197
  end
200
198
 
201
199
  def validate_triples!(transaction)
202
200
  existing_triples = containment_triples.to_a
203
-
204
- tx_containment = transaction.query(subject: subject_uri,
205
- predicate: RDF::Vocab::LDP.contains)
201
+
202
+ tx_containment = transaction.query(subject: subject_uri,
203
+ predicate: CONTAINS_URI)
206
204
 
207
205
  tx_containment.each do |statement|
208
- raise Conflict.new('Attempted to write unacceptable LDP ' \
209
- "containment-triple: #{statement}") unless
210
- existing_triples.include?(statement)
206
+ raise(Conflict, 'Attempted to write unacceptable LDP ' \
207
+ "containment-triple: #{statement}") unless
208
+ existing_triples.include?(statement)
211
209
  end
212
210
 
213
211
  deletes = existing_triples.reject { |st| tx_containment.include?(st) }
214
- raise Conflict.new('Cannot remove containment triples in updates. ' \
215
- "Attepted to remove #{deletes}") unless deletes.empty?
212
+ raise(Conflict, 'Cannot remove containment triples in updates. ' \
213
+ "Attepted to remove #{deletes}") unless deletes.empty?
216
214
  end
217
215
 
218
216
  ##
219
217
  # supports Patch.
220
218
  def validate_statements!(statements)
221
219
  existing_triples = containment_triples.to_a
222
- statements.query(subject: subject_uri,
223
- predicate: RDF::Vocab::LDP.contains) do |statement|
224
- existing_triples.delete(statement) do
225
- raise Conflict.new('Attempted to write unacceptable LDP ' \
226
- "containment-triple: #{statement}")
220
+ statements.query(subject: subject_uri, predicate: CONTAINS_URI) do |st|
221
+ existing_triples.delete(st) do
222
+ raise(Conflict, 'Attempted to write unacceptable LDP ' \
223
+ "containment-triple: #{st}")
227
224
  end
228
225
  end
229
- raise Conflict.new('Cannot remove containment triples in updates. ' \
230
- "Attepted to remove #{existing_triples}") unless
231
- existing_triples.empty?
226
+ raise(Conflict, 'Cannot remove containment triples in updates. ' \
227
+ "Attepted to remove #{existing_triples}") unless
228
+ existing_triples.empty?
232
229
  end
233
230
  end
234
231
  end
@@ -1,30 +1,33 @@
1
1
  module RDF::LDP
2
2
  ##
3
- # An extension of `RDF::LDP::Container` implementing direct containment.
4
- # This adds the concepts of a membership resource, predicate, and triples to
3
+ # An extension of `RDF::LDP::Container` implementing direct containment.
4
+ # This adds the concepts of a membership resource, predicate, and triples to
5
5
  # the Basic Container's containment triples.
6
6
  #
7
- # When the membership resource is an `RDFSource`, the membership triple is
7
+ # When the membership resource is an `RDFSource`, the membership triple is
8
8
  # added/removed from its graph when the resource created/deleted within the
9
- # container. When the membership resource is a `NonRDFSource`, the triple is
9
+ # container. When the membership resource is a `NonRDFSource`, the triple is
10
10
  # added/removed on its description's graph instead.
11
11
  #
12
12
  # A membership constant URI and membership predicate MUST be specified as
13
13
  # described in LDP--exactly one of each. If none is given, we default to
14
14
  # the container itself as a membership resource and `ldp:member` as predicate.
15
- # If more than one of either is given, all `#add/#remove` (POST/DELETE)
15
+ # If more than one of either is given, all `#add/#remove` (POST/DELETE)
16
16
  # requests will fail.
17
17
  #
18
18
  # @see http://www.w3.org/TR/ldp/#dfn-linked-data-platform-direct-container
19
19
  # definition of LDP Direct Container
20
20
  class DirectContainer < Container
21
+ MEMBER_URI = RDF::Vocab::LDP.member.freeze
22
+ MEMBERSHIP_RESOURCE_URI = RDF::Vocab::LDP.membershipResource.freeze
23
+
24
+ RELATION_TERMS = [RDF::Vocab::LDP.hasMemberRelation.freeze,
25
+ RDF::Vocab::LDP.isMemberOfRelation.freeze].freeze
26
+
21
27
  def self.to_uri
22
28
  RDF::Vocab::LDP.DirectContainer
23
29
  end
24
30
 
25
- RELATION_TERMS = [RDF::Vocab::LDP.hasMemberRelation,
26
- RDF::Vocab::LDP.isMemberOfRelation]
27
-
28
31
  ##
29
32
  # @return [RDF::URI] a URI representing the container type
30
33
  def container_class
@@ -34,16 +37,16 @@ module RDF::LDP
34
37
  ##
35
38
  # Creates and inserts default relation triples if none are given.
36
39
  #
37
- # @note the addition of default triples is handled in a separate
40
+ # @note the addition of default triples is handled in a separate
38
41
  # transaction. It is possible for the second transaction to fail, causing
39
42
  # the resource to persist in an invalid state. It is also possible for a
40
43
  # read to occur between the two transactions.
41
- # @todo Make atomic. Consider just raising an error instead of adding
42
- # triples. There's a need to handle this issue for repositories with
44
+ # @todo Make atomic. Consider just raising an error instead of adding
45
+ # triples. There's a need to handle this issue for repositories with
43
46
  # snapshot reads, as well as those without.
44
47
  #
45
48
  # @see Container#create
46
- def create(input, content_type, &block)
49
+ def create(input, content_type)
47
50
  super
48
51
 
49
52
  graph.transaction(mutable: true) do |tx|
@@ -63,8 +66,8 @@ module RDF::LDP
63
66
  # @see RDF::LDP::Container#add
64
67
  def add(resource, transaction = nil)
65
68
  target = transaction || graph
66
- process_membership_resource(resource) do |membership, quad, resource|
67
- super(resource, transaction)
69
+ process_membership_resource(resource) do |membership, quad, subject|
70
+ super(subject, transaction)
68
71
  target = transaction || membership.graph
69
72
  target.insert(quad)
70
73
  end
@@ -72,13 +75,13 @@ module RDF::LDP
72
75
  end
73
76
 
74
77
  ##
75
- # Removes a member `resource` to the container. Handles containment and
78
+ # Removes a member `resource` to the container. Handles containment and
76
79
  # removes membership triple to the memebership resource.
77
80
  #
78
81
  # @see RDF::LDP::Container#remove
79
82
  def remove(resource, transaction = nil)
80
- process_membership_resource(resource) do |membership, quad, resource|
81
- super(resource, transaction)
83
+ process_membership_resource(resource) do |membership, quad, subject|
84
+ super(subject, transaction)
82
85
  target = transaction || membership.graph
83
86
  target.delete(quad)
84
87
  end
@@ -86,24 +89,25 @@ module RDF::LDP
86
89
  end
87
90
 
88
91
  ##
89
- # Gives the membership constant URI. If none is present in the container
92
+ # Gives the membership constant URI. If none is present in the container
90
93
  # state, we add the current resource as a membership constant.
91
94
  #
92
95
  # @return [RDF::URI] the membership constant uri for the container
93
96
  #
94
- # @raise [RDF::LDP::NotAcceptable] if multiple membership constant uris exist
97
+ # @raise [RDF::LDP::NotAcceptable] if multiple membership constant uris
98
+ # exist
95
99
  #
96
100
  # @see http://www.w3.org/TR/ldp/#dfn-membership-triples
97
101
  def membership_constant_uri
98
102
  statements = membership_resource_statements
99
103
  return statements.first.object if statements.count == 1
100
104
 
101
- raise NotAcceptable.new('An LDP-DC MUST have exactly one membership ' \
102
- "resource; found #{statements.count}.")
105
+ raise(NotAcceptable, 'An LDP-DC MUST have exactly one membership ' \
106
+ "resource; found #{statements.count}.")
103
107
  end
104
108
 
105
109
  ##
106
- # Gives the membership predicate. If none is present in the container
110
+ # Gives the membership predicate. If none is present in the container
107
111
  # state, we add the current resource as a membership constant.
108
112
  #
109
113
  # @return [RDF::URI] the membership predicate
@@ -115,8 +119,8 @@ module RDF::LDP
115
119
  statements = member_relation_statements
116
120
  return statements.first.object if statements.count == 1
117
121
 
118
- raise NotAcceptable.new('An LDP-DC MUST have exactly one member ' \
119
- "relation triple; found #{statements.count}.")
122
+ raise(NotAcceptable, 'An LDP-DC MUST have exactly one member ' \
123
+ "relation triple; found #{statements.count}.")
120
124
  end
121
125
 
122
126
  ##
@@ -134,9 +138,9 @@ module RDF::LDP
134
138
  end
135
139
 
136
140
  private
137
-
141
+
138
142
  def membership_resource_statements
139
- graph.query([subject_uri, RDF::Vocab::LDP.membershipResource, :o])
143
+ graph.query([subject_uri, MEMBERSHIP_RESOURCE_URI, :o])
140
144
  end
141
145
 
142
146
  def member_relation_statements
@@ -153,28 +157,24 @@ module RDF::LDP
153
157
  resource
154
158
  end
155
159
 
156
- def process_membership_resource(resource, &block)
160
+ def process_membership_resource(resource)
157
161
  statement = make_membership_triple(resource.to_uri)
158
162
 
159
- begin
160
- membership_rs = membership_resource
161
- rescue NotFound => e
162
- raise NotAcceptable.new('Membership resource ' \
163
- "#{membership_constant_uri} does not exist")
164
- end
163
+ membership_rs = membership_resource
165
164
 
166
165
  statement.graph_name = membership_rs.subject_uri
167
166
  yield(membership_rs, statement, resource) if block_given?
167
+ rescue NotFound
168
+ raise(NotAcceptable, 'Membership resource ' \
169
+ "#{membership_constant_uri} does not exist")
168
170
  end
169
171
 
170
172
  def default_membership_resource_statement
171
- RDF::Statement(subject_uri,
172
- RDF::Vocab::LDP.membershipResource,
173
- subject_uri)
173
+ RDF::Statement(subject_uri, MEMBERSHIP_RESOURCE_URI, subject_uri)
174
174
  end
175
-
175
+
176
176
  def default_member_relation_statement
177
- RDF::Statement(subject_uri, RELATION_TERMS.first, RDF::Vocab::LDP.member)
177
+ RDF::Statement(subject_uri, RELATION_TERMS.first, MEMBER_URI)
178
178
  end
179
179
  end
180
180
  end