rdf-ldp 0.7.0 → 0.8.0

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: 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