atlas_rb 1.9.3 → 1.9.4
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 +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +38 -0
- data/Gemfile.lock +1 -1
- data/README.md +37 -0
- data/lib/atlas_rb/blob.rb +21 -8
- data/lib/atlas_rb/collection.rb +36 -12
- data/lib/atlas_rb/community.rb +30 -10
- data/lib/atlas_rb/compilation.rb +48 -16
- data/lib/atlas_rb/errors.rb +35 -11
- data/lib/atlas_rb/file_set.rb +18 -6
- data/lib/atlas_rb/person.rb +24 -8
- data/lib/atlas_rb/resource.rb +65 -0
- data/lib/atlas_rb/work.rb +60 -20
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 808bf4695fcba808f36a2c808885529bdff8b8dae50ddfed71cd605115aa9014
|
|
4
|
+
data.tar.gz: 532e5bac353cceeff1806829f4e8d8f2421051799b3a249bf3119c4001c144fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 177bfa1e9c486473285eba7fac243719f08af97ad58999fdb08c9d08725981ba8dce66143943768ff12a8e08d994ca34eb02a791cd567b7f98294732fd461a2a
|
|
7
|
+
data.tar.gz: 0eba14aa8d5ac54b4153fd48810c90fb979ac608cc3bf2b0fb68bdb039ed9b4db763d6610839a0656374f684fc9821bde4d3f7ae336f58ac9f894aa4aee2ad81
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.9.
|
|
1
|
+
1.9.4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.4
|
|
4
|
+
|
|
5
|
+
### Fixed — write bindings parsed the response body without checking the status
|
|
6
|
+
|
|
7
|
+
A write aimed at a resource that is not there raised
|
|
8
|
+
`JSON::ParserError: unexpected end of input at line 1 column 1`. Atlas is
|
|
9
|
+
correct here: it answers `head :not_found`, a `404` with an empty body. The
|
|
10
|
+
bindings then handed that empty body to `JSON.parse`.
|
|
11
|
+
|
|
12
|
+
The message named neither the verb nor the resource, so an operator whose XML
|
|
13
|
+
manifest carried a PID from another environment got five identical parser
|
|
14
|
+
errors and nothing to act on. `Resource.fetch_resource` already guarded the
|
|
15
|
+
**read** path against exactly this; the write half never got the same
|
|
16
|
+
treatment.
|
|
17
|
+
|
|
18
|
+
Every `create` / `update` / `metadata` / `parent` / `rollback` and sibling
|
|
19
|
+
across `Work`, `Collection`, `Community`, `Blob`, `FileSet`, `Compilation` and
|
|
20
|
+
`Person` now goes through a `write_resource` companion:
|
|
21
|
+
|
|
22
|
+
- `404` → {AtlasRb::NotFoundError}, naming the verb and path.
|
|
23
|
+
- `410` → the parsed body, as on the read path: an Idempotency-Key replay whose
|
|
24
|
+
resource has since been tombstoned answers `410 Gone` *with* the tombstone.
|
|
25
|
+
- any other non-2xx → {AtlasRb::ResourceError}, carrying Atlas's status + body.
|
|
26
|
+
- `2xx` → the parsed body, exactly as before.
|
|
27
|
+
|
|
28
|
+
`NotFoundError` subclasses `ResourceError`, so a caller that only wants "the
|
|
29
|
+
write failed" rescues the parent.
|
|
30
|
+
|
|
31
|
+
Note the deliberate asymmetry with the read path, which keeps returning `nil`
|
|
32
|
+
on a `404`: that answers a read, but not a write — the caller asked for a
|
|
33
|
+
change and did not get one.
|
|
34
|
+
|
|
35
|
+
Blast radius is which exception surfaces, not whether one does. The typed
|
|
36
|
+
`403` / `422` translations raise inside the Faraday stack, so they still fire
|
|
37
|
+
first; a `422` the middleware passes through on purpose (`tombstone`'s
|
|
38
|
+
`has_live_children`) is unaffected, because `tombstone`, `destroy` and
|
|
39
|
+
`complete` return the raw response and never parsed.
|
|
40
|
+
|
|
3
41
|
## 1.9.3
|
|
4
42
|
|
|
5
43
|
### Added — `depositor:` on `Collection.create` and `Community.create`
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -438,6 +438,43 @@ tombstoned resources come back flagged (`"tombstoned" => true`), so index
|
|
|
438
438
|
by `"noid"` rather than assuming positional correspondence. NOIDs only —
|
|
439
439
|
raw Valkyrie ids are not a supported input.
|
|
440
440
|
|
|
441
|
+
### Missing resources: `nil` on a read, a raise on a write
|
|
442
|
+
|
|
443
|
+
The two halves of the API answer an absent resource differently, on purpose.
|
|
444
|
+
|
|
445
|
+
A **read** returns `nil`. "There is nothing there" is a legitimate answer to a
|
|
446
|
+
question, and callers already nil-check a `find`:
|
|
447
|
+
|
|
448
|
+
```ruby
|
|
449
|
+
AtlasRb::Work.find("doesnotexist") # => nil
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
A **write** raises `AtlasRb::NotFoundError`. The caller asked for a change and
|
|
453
|
+
did not get one, so `nil` would invite the silent failure the read guard was
|
|
454
|
+
written to prevent:
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
begin
|
|
458
|
+
AtlasRb::Work.update("doesnotexist", "/tmp/mods.xml")
|
|
459
|
+
rescue AtlasRb::NotFoundError => e
|
|
460
|
+
e.status # => 404
|
|
461
|
+
e.message # => "PATCH /works/doesnotexist → 404 (no such resource)"
|
|
462
|
+
end
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
This covers every `create` / `update` / `metadata` / `parent` / `rollback` and
|
|
466
|
+
their siblings on `Work`, `Collection`, `Community`, `Blob`, `FileSet`,
|
|
467
|
+
`Compilation` and `Person`. Any other non-2xx a write gets raises
|
|
468
|
+
`AtlasRb::ResourceError`, which `NotFoundError` subclasses — so a caller that
|
|
469
|
+
only wants "the write failed" rescues the parent.
|
|
470
|
+
|
|
471
|
+
Two neighbours are deliberately untouched. A `410 Gone` is returned, not
|
|
472
|
+
raised, the same way a read returns it: an `Idempotency-Key` replay whose
|
|
473
|
+
resource has since been tombstoned answers `410` *with* the tombstone, and the
|
|
474
|
+
caller reads `tombstoned`. And the typed `403` / `422` translations above still
|
|
475
|
+
fire first, while `tombstone` / `destroy` / `complete` keep returning the raw
|
|
476
|
+
Faraday response for the caller to read.
|
|
477
|
+
|
|
441
478
|
## End-to-end example
|
|
442
479
|
|
|
443
480
|
JSON responses come back as `AtlasRb::Mash` (a `Hashie::Mash` subclass), so
|
data/lib/atlas_rb/blob.rb
CHANGED
|
@@ -157,6 +157,10 @@ module AtlasRb
|
|
|
157
157
|
# `"digest"` (the recorded fixity digest, `"sha512:<hex>"`).
|
|
158
158
|
# @raise [AtlasRb::FixityMismatchError] if `expected_digest` was supplied and
|
|
159
159
|
# the uploaded bytes did not match (or the algorithm is unsupported).
|
|
160
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
161
|
+
# resource, so the write did not happen.
|
|
162
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
163
|
+
# and body.
|
|
160
164
|
#
|
|
161
165
|
# @note Streams the file (FD closed deterministically); a multi-GB upload is
|
|
162
166
|
# not buffered in memory. See {AtlasRb::FaradayHelper#with_file_part}.
|
|
@@ -175,9 +179,9 @@ module AtlasRb
|
|
|
175
179
|
payload = { work_id: id, original_filename: original_filename, binary: part }
|
|
176
180
|
payload[:expected_digest] = expected_digest if expected_digest
|
|
177
181
|
|
|
178
|
-
AtlasRb::Mash.new(
|
|
182
|
+
AtlasRb::Mash.new(write_resource(
|
|
179
183
|
multipart(nuid, on_behalf_of: on_behalf_of, idempotency_key: idempotency_key)
|
|
180
|
-
.post(ROUTE, payload)
|
|
184
|
+
.post(ROUTE, payload)
|
|
181
185
|
))['blob']
|
|
182
186
|
end
|
|
183
187
|
end
|
|
@@ -223,6 +227,10 @@ module AtlasRb
|
|
|
223
227
|
# `"blob"`, with a refreshed `"digest"` for the new revision).
|
|
224
228
|
# @raise [AtlasRb::FixityMismatchError] if `expected_digest` was supplied and
|
|
225
229
|
# the uploaded bytes did not match (or the algorithm is unsupported).
|
|
230
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
231
|
+
# resource, so the write did not happen.
|
|
232
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
233
|
+
# and body.
|
|
226
234
|
#
|
|
227
235
|
# @note Streams the file with the FD closed deterministically — see {.create}.
|
|
228
236
|
#
|
|
@@ -236,9 +244,9 @@ module AtlasRb
|
|
|
236
244
|
payload = { binary: part }
|
|
237
245
|
payload[:expected_digest] = expected_digest if expected_digest
|
|
238
246
|
|
|
239
|
-
AtlasRb::Mash.new(
|
|
247
|
+
AtlasRb::Mash.new(write_resource(
|
|
240
248
|
multipart(nuid, on_behalf_of: on_behalf_of, idempotency_key: idempotency_key)
|
|
241
|
-
.patch(ROUTE + id, payload)
|
|
249
|
+
.patch(ROUTE + id, payload)
|
|
242
250
|
))
|
|
243
251
|
end
|
|
244
252
|
end
|
|
@@ -324,8 +332,9 @@ module AtlasRb
|
|
|
324
332
|
# recopied. Avoids a full round-trip of the bytes back through the caller
|
|
325
333
|
# (vs. re-streaming {.version_content} into {.update}).
|
|
326
334
|
#
|
|
327
|
-
# Pass a `version_id` obtained from {.versions}.
|
|
328
|
-
#
|
|
335
|
+
# Pass a `version_id` obtained from {.versions}. Atlas answers an unknown id
|
|
336
|
+
# or version with a `404`, which raises {AtlasRb::NotFoundError} — a write
|
|
337
|
+
# that did not happen must not read like one that did.
|
|
329
338
|
#
|
|
330
339
|
# @param id [String] the Blob ID.
|
|
331
340
|
# @param version_id [String] the OCFL version label to reinstate, e.g. `"v1"`.
|
|
@@ -337,13 +346,17 @@ module AtlasRb
|
|
|
337
346
|
# omitted.
|
|
338
347
|
# @return [AtlasRb::Mash] the updated `"blob"` payload (NOID unchanged,
|
|
339
348
|
# `"digest"` refreshed to the reinstated bytes).
|
|
349
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
350
|
+
# resource, so the write did not happen.
|
|
351
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
352
|
+
# and body.
|
|
340
353
|
#
|
|
341
354
|
# @example
|
|
342
355
|
# AtlasRb::Blob.rollback("b-321", "v1")
|
|
343
356
|
def self.rollback(id, version_id, nuid: nil, on_behalf_of: nil)
|
|
344
|
-
AtlasRb::Mash.new(
|
|
357
|
+
AtlasRb::Mash.new(write_resource(
|
|
345
358
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
346
|
-
.post("#{ROUTE}#{id}/rollback", JSON.dump(version_id: version_id))
|
|
359
|
+
.post("#{ROUTE}#{id}/rollback", JSON.dump(version_id: version_id))
|
|
347
360
|
))['blob']
|
|
348
361
|
end
|
|
349
362
|
end
|
data/lib/atlas_rb/collection.rb
CHANGED
|
@@ -66,6 +66,10 @@ module AtlasRb
|
|
|
66
66
|
# is immutable post-create; there is no setter on the update surface.
|
|
67
67
|
# @return [Hash] the created Collection payload (post-update if
|
|
68
68
|
# `xml_path` was supplied).
|
|
69
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
70
|
+
# resource, so the write did not happen.
|
|
71
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
72
|
+
# and body.
|
|
69
73
|
#
|
|
70
74
|
# @example A featured showcase collection
|
|
71
75
|
# AtlasRb::Collection.create("c-123", featured: true)
|
|
@@ -75,8 +79,8 @@ module AtlasRb
|
|
|
75
79
|
def self.create(id, xml_path = nil, featured: false, nuid: nil, on_behalf_of: nil, depositor: nil)
|
|
76
80
|
params = { parent_id: id, featured: featured }
|
|
77
81
|
params[:depositor] = depositor if depositor
|
|
78
|
-
result = AtlasRb::Mash.new(
|
|
79
|
-
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
82
|
+
result = AtlasRb::Mash.new(write_resource(
|
|
83
|
+
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
80
84
|
))["collection"]
|
|
81
85
|
return result if xml_path.to_s.empty?
|
|
82
86
|
|
|
@@ -96,12 +100,16 @@ module AtlasRb
|
|
|
96
100
|
# @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
|
|
97
101
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when omitted.
|
|
98
102
|
# @return [AtlasRb::Mash] the updated `"collection"` object, already unwrapped.
|
|
103
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
104
|
+
# resource, so the write did not happen.
|
|
105
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
106
|
+
# and body.
|
|
99
107
|
#
|
|
100
108
|
# @example
|
|
101
109
|
# AtlasRb::Collection.set_featured("col-456", true)
|
|
102
110
|
def self.set_featured(id, featured, nuid: nil, on_behalf_of: nil)
|
|
103
|
-
AtlasRb::Mash.new(
|
|
104
|
-
connection({ featured: featured }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
111
|
+
AtlasRb::Mash.new(write_resource(
|
|
112
|
+
connection({ featured: featured }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
105
113
|
))["collection"]
|
|
106
114
|
end
|
|
107
115
|
|
|
@@ -134,13 +142,17 @@ module AtlasRb
|
|
|
134
142
|
# envelope's `error` code is exposed as `#code`.
|
|
135
143
|
# @raise [AtlasRb::ForbiddenError] if Atlas refuses the move on
|
|
136
144
|
# authorization grounds (HTTP 403).
|
|
145
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
146
|
+
# resource, so the write did not happen.
|
|
147
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
148
|
+
# and body.
|
|
137
149
|
#
|
|
138
150
|
# @example
|
|
139
151
|
# AtlasRb::Collection.reparent("col-456", "c-999")
|
|
140
152
|
def self.reparent(id, new_parent_id, nuid: nil, on_behalf_of: nil)
|
|
141
|
-
AtlasRb::Mash.new(
|
|
153
|
+
AtlasRb::Mash.new(write_resource(
|
|
142
154
|
connection({ parent_id: new_parent_id }, nuid, on_behalf_of: on_behalf_of)
|
|
143
|
-
.patch(ROUTE + id + '/parent')
|
|
155
|
+
.patch(ROUTE + id + '/parent')
|
|
144
156
|
))["collection"]
|
|
145
157
|
end
|
|
146
158
|
|
|
@@ -200,6 +212,10 @@ module AtlasRb
|
|
|
200
212
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
201
213
|
# omitted.
|
|
202
214
|
# @return [Hash] the parsed JSON response from the patch.
|
|
215
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
216
|
+
# resource, so the write did not happen.
|
|
217
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
218
|
+
# and body.
|
|
203
219
|
#
|
|
204
220
|
# @example
|
|
205
221
|
# AtlasRb::Collection.update("col-456", "/tmp/collection-mods.xml")
|
|
@@ -207,8 +223,8 @@ module AtlasRb
|
|
|
207
223
|
payload = { binary: Faraday::Multipart::FilePart.new(File.open(xml_path),
|
|
208
224
|
"application/xml",
|
|
209
225
|
File.basename(xml_path)) }
|
|
210
|
-
AtlasRb::Mash.new(
|
|
211
|
-
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
226
|
+
AtlasRb::Mash.new(write_resource(
|
|
227
|
+
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
212
228
|
))
|
|
213
229
|
end
|
|
214
230
|
|
|
@@ -228,12 +244,16 @@ module AtlasRb
|
|
|
228
244
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
229
245
|
# omitted.
|
|
230
246
|
# @return [Hash] the parsed JSON response.
|
|
247
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
248
|
+
# resource, so the write did not happen.
|
|
249
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
250
|
+
# and body.
|
|
231
251
|
#
|
|
232
252
|
# @example
|
|
233
253
|
# AtlasRb::Collection.metadata("col-456", title: "Renamed Collection")
|
|
234
254
|
def self.metadata(id, values, nuid: nil, on_behalf_of: nil)
|
|
235
|
-
AtlasRb::Mash.new(
|
|
236
|
-
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
255
|
+
AtlasRb::Mash.new(write_resource(
|
|
256
|
+
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
237
257
|
))
|
|
238
258
|
end
|
|
239
259
|
|
|
@@ -255,6 +275,10 @@ module AtlasRb
|
|
|
255
275
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
256
276
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
257
277
|
# `error: "stale_resource"`).
|
|
278
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
279
|
+
# resource, so the write did not happen.
|
|
280
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
281
|
+
# and body.
|
|
258
282
|
#
|
|
259
283
|
# @example
|
|
260
284
|
# AtlasRb::Collection.set_thumbnails(
|
|
@@ -265,9 +289,9 @@ module AtlasRb
|
|
|
265
289
|
# )
|
|
266
290
|
def self.set_thumbnails(id, thumbnail: nil, thumbnail_2x: nil, preview: nil, nuid: nil, on_behalf_of: nil)
|
|
267
291
|
body = { thumbnail: thumbnail, thumbnail_2x: thumbnail_2x, preview: preview }.compact
|
|
268
|
-
AtlasRb::Mash.new(
|
|
292
|
+
AtlasRb::Mash.new(write_resource(
|
|
269
293
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
270
|
-
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
294
|
+
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
271
295
|
))
|
|
272
296
|
end
|
|
273
297
|
|
data/lib/atlas_rb/community.rb
CHANGED
|
@@ -61,6 +61,10 @@ module AtlasRb
|
|
|
61
61
|
# is immutable post-create; there is no setter on the update surface.
|
|
62
62
|
# @return [Hash] the created Community payload (post-update if `xml_path`
|
|
63
63
|
# was supplied).
|
|
64
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
65
|
+
# resource, so the write did not happen.
|
|
66
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
67
|
+
# and body.
|
|
64
68
|
#
|
|
65
69
|
# @example Top-level community, no metadata
|
|
66
70
|
# AtlasRb::Community.create(nil)
|
|
@@ -73,8 +77,8 @@ module AtlasRb
|
|
|
73
77
|
def self.create(id = nil, xml_path = nil, nuid: nil, on_behalf_of: nil, depositor: nil)
|
|
74
78
|
params = { parent_id: id }
|
|
75
79
|
params[:depositor] = depositor if depositor
|
|
76
|
-
result = AtlasRb::Mash.new(
|
|
77
|
-
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
80
|
+
result = AtlasRb::Mash.new(write_resource(
|
|
81
|
+
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
78
82
|
))["community"]
|
|
79
83
|
return result if xml_path.to_s.empty?
|
|
80
84
|
|
|
@@ -113,6 +117,10 @@ module AtlasRb
|
|
|
113
117
|
# `parent_not_found`). The envelope's `error` code is exposed as `#code`.
|
|
114
118
|
# @raise [AtlasRb::ForbiddenError] if Atlas refuses the move on
|
|
115
119
|
# authorization grounds (HTTP 403).
|
|
120
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
121
|
+
# resource, so the write did not happen.
|
|
122
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
123
|
+
# and body.
|
|
116
124
|
#
|
|
117
125
|
# @example Move under another Community
|
|
118
126
|
# AtlasRb::Community.reparent("c-123", "c-999")
|
|
@@ -120,9 +128,9 @@ module AtlasRb
|
|
|
120
128
|
# @example Promote to a top-level Community
|
|
121
129
|
# AtlasRb::Community.reparent("c-123", nil)
|
|
122
130
|
def self.reparent(id, new_parent_id, nuid: nil, on_behalf_of: nil)
|
|
123
|
-
AtlasRb::Mash.new(
|
|
131
|
+
AtlasRb::Mash.new(write_resource(
|
|
124
132
|
connection({ parent_id: new_parent_id }, nuid, on_behalf_of: on_behalf_of)
|
|
125
|
-
.patch(ROUTE + id + '/parent')
|
|
133
|
+
.patch(ROUTE + id + '/parent')
|
|
126
134
|
))["community"]
|
|
127
135
|
end
|
|
128
136
|
|
|
@@ -183,6 +191,10 @@ module AtlasRb
|
|
|
183
191
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
184
192
|
# omitted.
|
|
185
193
|
# @return [Hash] the parsed JSON response from the patch.
|
|
194
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
195
|
+
# resource, so the write did not happen.
|
|
196
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
197
|
+
# and body.
|
|
186
198
|
#
|
|
187
199
|
# @example
|
|
188
200
|
# AtlasRb::Community.update("c-123", "/tmp/community-mods.xml")
|
|
@@ -190,8 +202,8 @@ module AtlasRb
|
|
|
190
202
|
payload = { binary: Faraday::Multipart::FilePart.new(File.open(xml_path),
|
|
191
203
|
"application/xml",
|
|
192
204
|
File.basename(xml_path)) }
|
|
193
|
-
AtlasRb::Mash.new(
|
|
194
|
-
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
205
|
+
AtlasRb::Mash.new(write_resource(
|
|
206
|
+
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
195
207
|
))
|
|
196
208
|
end
|
|
197
209
|
|
|
@@ -212,12 +224,16 @@ module AtlasRb
|
|
|
212
224
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
213
225
|
# omitted.
|
|
214
226
|
# @return [Hash] the parsed JSON response.
|
|
227
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
228
|
+
# resource, so the write did not happen.
|
|
229
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
230
|
+
# and body.
|
|
215
231
|
#
|
|
216
232
|
# @example
|
|
217
233
|
# AtlasRb::Community.metadata("c-123", title: "New Name")
|
|
218
234
|
def self.metadata(id, values, nuid: nil, on_behalf_of: nil)
|
|
219
|
-
AtlasRb::Mash.new(
|
|
220
|
-
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
235
|
+
AtlasRb::Mash.new(write_resource(
|
|
236
|
+
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
221
237
|
))
|
|
222
238
|
end
|
|
223
239
|
|
|
@@ -239,6 +255,10 @@ module AtlasRb
|
|
|
239
255
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
240
256
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
241
257
|
# `error: "stale_resource"`).
|
|
258
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
259
|
+
# resource, so the write did not happen.
|
|
260
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
261
|
+
# and body.
|
|
242
262
|
#
|
|
243
263
|
# @example
|
|
244
264
|
# AtlasRb::Community.set_thumbnails(
|
|
@@ -249,9 +269,9 @@ module AtlasRb
|
|
|
249
269
|
# )
|
|
250
270
|
def self.set_thumbnails(id, thumbnail: nil, thumbnail_2x: nil, preview: nil, nuid: nil, on_behalf_of: nil)
|
|
251
271
|
body = { thumbnail: thumbnail, thumbnail_2x: thumbnail_2x, preview: preview }.compact
|
|
252
|
-
AtlasRb::Mash.new(
|
|
272
|
+
AtlasRb::Mash.new(write_resource(
|
|
253
273
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
254
|
-
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
274
|
+
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
255
275
|
))
|
|
256
276
|
end
|
|
257
277
|
|
data/lib/atlas_rb/compilation.rb
CHANGED
|
@@ -136,6 +136,10 @@ module AtlasRb
|
|
|
136
136
|
# e.g. a blank title).
|
|
137
137
|
# @raise [AtlasRb::ForbiddenError] if the caller may not create Sets
|
|
138
138
|
# (guests cannot).
|
|
139
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
140
|
+
# resource, so the write did not happen.
|
|
141
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
142
|
+
# and body.
|
|
139
143
|
#
|
|
140
144
|
# @example
|
|
141
145
|
# AtlasRb::Compilation.create("Course readings",
|
|
@@ -144,8 +148,8 @@ module AtlasRb
|
|
|
144
148
|
def self.create(title, description: nil, nuid: nil, on_behalf_of: nil)
|
|
145
149
|
params = { title: title }
|
|
146
150
|
params[:description] = description if description
|
|
147
|
-
AtlasRb::Mash.new(
|
|
148
|
-
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
151
|
+
AtlasRb::Mash.new(write_resource(
|
|
152
|
+
connection(params, nuid, on_behalf_of: on_behalf_of).post(ROUTE)
|
|
149
153
|
))["compilation"]
|
|
150
154
|
end
|
|
151
155
|
|
|
@@ -172,6 +176,10 @@ module AtlasRb
|
|
|
172
176
|
# @raise [AtlasRb::CompilationError] if Atlas rejects the update (422).
|
|
173
177
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights
|
|
174
178
|
# (owner / explicit grant / admin).
|
|
179
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
180
|
+
# resource, so the write did not happen.
|
|
181
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
182
|
+
# and body.
|
|
175
183
|
#
|
|
176
184
|
# @example Rename
|
|
177
185
|
# AtlasRb::Compilation.update("c-123", title: "Renamed", nuid: "000000002")
|
|
@@ -185,8 +193,8 @@ module AtlasRb
|
|
|
185
193
|
params[:title] = title if title
|
|
186
194
|
params[:description] = description if description
|
|
187
195
|
params[:permissions] = permissions if permissions
|
|
188
|
-
AtlasRb::Mash.new(
|
|
189
|
-
connection(params, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
196
|
+
AtlasRb::Mash.new(write_resource(
|
|
197
|
+
connection(params, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
190
198
|
))["compilation"]
|
|
191
199
|
end
|
|
192
200
|
|
|
@@ -231,13 +239,17 @@ module AtlasRb
|
|
|
231
239
|
# the full recipe, so chip counts refresh without a follow-up {.find}.
|
|
232
240
|
# @raise [AtlasRb::CompilationError] if the noid is not a Collection (422).
|
|
233
241
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
242
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
243
|
+
# resource, so the write did not happen.
|
|
244
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
245
|
+
# and body.
|
|
234
246
|
#
|
|
235
247
|
# @example
|
|
236
248
|
# AtlasRb::Compilation.add_included_collection("c-123", "col-456", nuid: "000000002")
|
|
237
249
|
def self.add_included_collection(id, collection_id, nuid: nil, on_behalf_of: nil)
|
|
238
|
-
AtlasRb::Mash.new(
|
|
250
|
+
AtlasRb::Mash.new(write_resource(
|
|
239
251
|
connection({ collection_id: collection_id }, nuid, on_behalf_of: on_behalf_of)
|
|
240
|
-
.post(ROUTE + id + '/included_collections')
|
|
252
|
+
.post(ROUTE + id + '/included_collections')
|
|
241
253
|
))["compilation"]
|
|
242
254
|
end
|
|
243
255
|
|
|
@@ -256,13 +268,17 @@ module AtlasRb
|
|
|
256
268
|
# omitted.
|
|
257
269
|
# @return [Hash] the updated `"compilation"` object.
|
|
258
270
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
271
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
272
|
+
# resource, so the write did not happen.
|
|
273
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
274
|
+
# and body.
|
|
259
275
|
#
|
|
260
276
|
# @example
|
|
261
277
|
# AtlasRb::Compilation.remove_included_collection("c-123", "col-456", nuid: "000000002")
|
|
262
278
|
def self.remove_included_collection(id, collection_id, nuid: nil, on_behalf_of: nil)
|
|
263
|
-
AtlasRb::Mash.new(
|
|
279
|
+
AtlasRb::Mash.new(write_resource(
|
|
264
280
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
265
|
-
.delete(ROUTE + id + '/included_collections/' + collection_id)
|
|
281
|
+
.delete(ROUTE + id + '/included_collections/' + collection_id)
|
|
266
282
|
))["compilation"]
|
|
267
283
|
end
|
|
268
284
|
|
|
@@ -281,13 +297,17 @@ module AtlasRb
|
|
|
281
297
|
# @return [Hash] the updated `"compilation"` object.
|
|
282
298
|
# @raise [AtlasRb::CompilationError] if the noid is not a Work (422).
|
|
283
299
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
300
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
301
|
+
# resource, so the write did not happen.
|
|
302
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
303
|
+
# and body.
|
|
284
304
|
#
|
|
285
305
|
# @example
|
|
286
306
|
# AtlasRb::Compilation.add_included_work("c-123", "w-789", nuid: "000000002")
|
|
287
307
|
def self.add_included_work(id, work_id, nuid: nil, on_behalf_of: nil)
|
|
288
|
-
AtlasRb::Mash.new(
|
|
308
|
+
AtlasRb::Mash.new(write_resource(
|
|
289
309
|
connection({ work_id: work_id }, nuid, on_behalf_of: on_behalf_of)
|
|
290
|
-
.post(ROUTE + id + '/included_works')
|
|
310
|
+
.post(ROUTE + id + '/included_works')
|
|
291
311
|
))["compilation"]
|
|
292
312
|
end
|
|
293
313
|
|
|
@@ -303,13 +323,17 @@ module AtlasRb
|
|
|
303
323
|
# omitted.
|
|
304
324
|
# @return [Hash] the updated `"compilation"` object.
|
|
305
325
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
326
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
327
|
+
# resource, so the write did not happen.
|
|
328
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
329
|
+
# and body.
|
|
306
330
|
#
|
|
307
331
|
# @example
|
|
308
332
|
# AtlasRb::Compilation.remove_included_work("c-123", "w-789", nuid: "000000002")
|
|
309
333
|
def self.remove_included_work(id, work_id, nuid: nil, on_behalf_of: nil)
|
|
310
|
-
AtlasRb::Mash.new(
|
|
334
|
+
AtlasRb::Mash.new(write_resource(
|
|
311
335
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
312
|
-
.delete(ROUTE + id + '/included_works/' + work_id)
|
|
336
|
+
.delete(ROUTE + id + '/included_works/' + work_id)
|
|
313
337
|
))["compilation"]
|
|
314
338
|
end
|
|
315
339
|
|
|
@@ -331,13 +355,17 @@ module AtlasRb
|
|
|
331
355
|
# @return [Hash] the updated `"compilation"` object.
|
|
332
356
|
# @raise [AtlasRb::CompilationError] if the noid is not a Work (422).
|
|
333
357
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
358
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
359
|
+
# resource, so the write did not happen.
|
|
360
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
361
|
+
# and body.
|
|
334
362
|
#
|
|
335
363
|
# @example
|
|
336
364
|
# AtlasRb::Compilation.add_exclusion("c-123", "w-789", nuid: "000000002")
|
|
337
365
|
def self.add_exclusion(id, work_id, nuid: nil, on_behalf_of: nil)
|
|
338
|
-
AtlasRb::Mash.new(
|
|
366
|
+
AtlasRb::Mash.new(write_resource(
|
|
339
367
|
connection({ work_id: work_id }, nuid, on_behalf_of: on_behalf_of)
|
|
340
|
-
.post(ROUTE + id + '/exclusions')
|
|
368
|
+
.post(ROUTE + id + '/exclusions')
|
|
341
369
|
))["compilation"]
|
|
342
370
|
end
|
|
343
371
|
|
|
@@ -353,13 +381,17 @@ module AtlasRb
|
|
|
353
381
|
# omitted.
|
|
354
382
|
# @return [Hash] the updated `"compilation"` object.
|
|
355
383
|
# @raise [AtlasRb::ForbiddenError] if the caller lacks edit rights.
|
|
384
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
385
|
+
# resource, so the write did not happen.
|
|
386
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
387
|
+
# and body.
|
|
356
388
|
#
|
|
357
389
|
# @example
|
|
358
390
|
# AtlasRb::Compilation.remove_exclusion("c-123", "w-789", nuid: "000000002")
|
|
359
391
|
def self.remove_exclusion(id, work_id, nuid: nil, on_behalf_of: nil)
|
|
360
|
-
AtlasRb::Mash.new(
|
|
392
|
+
AtlasRb::Mash.new(write_resource(
|
|
361
393
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
362
|
-
.delete(ROUTE + id + '/exclusions/' + work_id)
|
|
394
|
+
.delete(ROUTE + id + '/exclusions/' + work_id)
|
|
363
395
|
))["compilation"]
|
|
364
396
|
end
|
|
365
397
|
|
data/lib/atlas_rb/errors.rb
CHANGED
|
@@ -275,12 +275,16 @@ module AtlasRb
|
|
|
275
275
|
end
|
|
276
276
|
end
|
|
277
277
|
|
|
278
|
-
# Raised
|
|
279
|
-
#
|
|
280
|
-
#
|
|
281
|
-
#
|
|
282
|
-
#
|
|
283
|
-
#
|
|
278
|
+
# Raised when Atlas answers a single-resource request with a non-2xx the
|
|
279
|
+
# binding cannot represent as a return value:
|
|
280
|
+
#
|
|
281
|
+
# - on a **read** ({Resource.find} and the `Work` / `Collection` /
|
|
282
|
+
# `Community` / `FileSet` / `Person` / `Compilation` / `Blob` / `Delegate`
|
|
283
|
+
# overrides), any non-2xx that is **not** a `404` or a `410` — i.e. an error
|
|
284
|
+
# envelope (`{ "error" => ... }`, status 400/401/403/422) on what the caller
|
|
285
|
+
# treated as a plain read.
|
|
286
|
+
# - on a **write** (`create`, `update`, `metadata`, and their siblings), any
|
|
287
|
+
# non-2xx at all; a `404` there is the {NotFoundError} subclass.
|
|
284
288
|
#
|
|
285
289
|
# Before this existed, `find` unwrapped the success body by a fixed key
|
|
286
290
|
# (`["work"]`, `["collection"]`, …); on an error envelope that key is
|
|
@@ -291,11 +295,11 @@ module AtlasRb
|
|
|
291
295
|
# real cause (e.g. `… → 401: {"error":"invalid bearer token"}`) is
|
|
292
296
|
# attributable everywhere `find` is used.
|
|
293
297
|
#
|
|
294
|
-
#
|
|
295
|
-
# "not found" is a normal `find` outcome callers already
|
|
296
|
-
# is also **not** this — a tombstoned resource comes back
|
|
297
|
-
# its full body, which `find` returns (the caller
|
|
298
|
-
# `tombstoned`), rather than an error to raise.
|
|
298
|
+
# On the read path a genuine `404` is **not** this — it stays a clean `nil`
|
|
299
|
+
# return, since "not found" is a normal `find` outcome callers already
|
|
300
|
+
# nil-check. A `410` is also **not** this — a tombstoned resource comes back
|
|
301
|
+
# as `410 Gone` with its full body, which `find` returns (the caller
|
|
302
|
+
# nil-checks / reads `tombstoned`), rather than an error to raise.
|
|
299
303
|
#
|
|
300
304
|
# @note Authorization failures on the narrow re-parent / linked-member /
|
|
301
305
|
# Compilation write paths surface as {ForbiddenError} via
|
|
@@ -322,6 +326,26 @@ module AtlasRb
|
|
|
322
326
|
end
|
|
323
327
|
end
|
|
324
328
|
|
|
329
|
+
# Raised when a **write** binding (`create`, `update`, `metadata`, `parent`,
|
|
330
|
+
# `rollback`, and their siblings) targets a resource Atlas answers `404` for —
|
|
331
|
+
# a mistyped or foreign NOID, or one re-parented away.
|
|
332
|
+
#
|
|
333
|
+
# A `404` on the read path is not this: {Resource.find} and its typed
|
|
334
|
+
# overrides return a clean `nil`, because "there is nothing there" answers a
|
|
335
|
+
# read. It cannot answer a write — the caller asked for a change that did not
|
|
336
|
+
# happen — so the write path raises instead of coercing to `nil`. Atlas
|
|
337
|
+
# renders the refusal as `head :not_found` with an empty body, which is what
|
|
338
|
+
# made the old blind `JSON.parse` surface it as
|
|
339
|
+
# `JSON::ParserError: unexpected end of input`: a message naming neither the
|
|
340
|
+
# resource nor the verb.
|
|
341
|
+
#
|
|
342
|
+
# rescue AtlasRb::NotFoundError => e
|
|
343
|
+
# report.rows.failed(row, "no such object in this repository")
|
|
344
|
+
#
|
|
345
|
+
# A subclass of {ResourceError}, so it carries the same `status` / `body` and
|
|
346
|
+
# a caller that only wants "the write failed" can rescue the parent.
|
|
347
|
+
class NotFoundError < ResourceError; end
|
|
348
|
+
|
|
325
349
|
# Raised when the transport has no way to authenticate a relay request:
|
|
326
350
|
# neither `ATLAS_JWT` (BYO-JWT mode) nor a signing key
|
|
327
351
|
# ({AtlasRb.config#assertion_signing_key}, relay-signing mode) is configured.
|
data/lib/atlas_rb/file_set.rb
CHANGED
|
@@ -59,6 +59,10 @@ module AtlasRb
|
|
|
59
59
|
# @return [Hash] the created `"file_set"` payload, including its `"id"`
|
|
60
60
|
# which can then be passed to {.update} to attach a binary, and its
|
|
61
61
|
# `"position"` (`nil` when unordered).
|
|
62
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
63
|
+
# resource, so the write did not happen.
|
|
64
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
65
|
+
# and body.
|
|
62
66
|
#
|
|
63
67
|
# @example
|
|
64
68
|
# fs = AtlasRb::FileSet.create("w-789", "primary")
|
|
@@ -74,9 +78,9 @@ module AtlasRb
|
|
|
74
78
|
def self.create(id, classification, position: nil, idempotency_key: nil, nuid: nil, on_behalf_of: nil)
|
|
75
79
|
params = { work_id: id, classification: classification }
|
|
76
80
|
params[:position] = position if position
|
|
77
|
-
AtlasRb::Mash.new(
|
|
81
|
+
AtlasRb::Mash.new(write_resource(
|
|
78
82
|
connection(params, nuid,
|
|
79
|
-
on_behalf_of: on_behalf_of, idempotency_key: idempotency_key).post(ROUTE)
|
|
83
|
+
on_behalf_of: on_behalf_of, idempotency_key: idempotency_key).post(ROUTE)
|
|
80
84
|
))["file_set"]
|
|
81
85
|
end
|
|
82
86
|
|
|
@@ -123,6 +127,10 @@ module AtlasRb
|
|
|
123
127
|
# @return [Hash] the parsed JSON response from the patch (the `"file_set"`).
|
|
124
128
|
# @raise [AtlasRb::FixityMismatchError] if `expected_digest` was supplied and
|
|
125
129
|
# the uploaded bytes did not match (or the algorithm is unsupported).
|
|
130
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
131
|
+
# resource, so the write did not happen.
|
|
132
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
133
|
+
# and body.
|
|
126
134
|
#
|
|
127
135
|
# @note Streams the file with the FD closed deterministically — see
|
|
128
136
|
# {Blob.create} / {AtlasRb::FaradayHelper#with_file_part}.
|
|
@@ -141,9 +149,9 @@ module AtlasRb
|
|
|
141
149
|
payload[:original_filename] = original_filename if original_filename
|
|
142
150
|
payload[:expected_digest] = expected_digest if expected_digest
|
|
143
151
|
|
|
144
|
-
AtlasRb::Mash.new(
|
|
152
|
+
AtlasRb::Mash.new(write_resource(
|
|
145
153
|
multipart(nuid, on_behalf_of: on_behalf_of, idempotency_key: idempotency_key)
|
|
146
|
-
.patch(ROUTE + id, payload)
|
|
154
|
+
.patch(ROUTE + id, payload)
|
|
147
155
|
))
|
|
148
156
|
end
|
|
149
157
|
end
|
|
@@ -172,6 +180,10 @@ module AtlasRb
|
|
|
172
180
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
173
181
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
174
182
|
# `error: "stale_resource"`).
|
|
183
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
184
|
+
# resource, so the write did not happen.
|
|
185
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
186
|
+
# and body.
|
|
175
187
|
#
|
|
176
188
|
# @example
|
|
177
189
|
# AtlasRb::FileSet.set_iiif_service(
|
|
@@ -179,9 +191,9 @@ module AtlasRb
|
|
|
179
191
|
# "https://iiif.example.edu/iiif/3/abc.jp2"
|
|
180
192
|
# )
|
|
181
193
|
def self.set_iiif_service(id, uri, nuid: nil, on_behalf_of: nil)
|
|
182
|
-
AtlasRb::Mash.new(
|
|
194
|
+
AtlasRb::Mash.new(write_resource(
|
|
183
195
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
184
|
-
.patch(ROUTE + id + "/iiif_service", JSON.dump({ uri: uri }))
|
|
196
|
+
.patch(ROUTE + id + "/iiif_service", JSON.dump({ uri: uri }))
|
|
185
197
|
))
|
|
186
198
|
end
|
|
187
199
|
end
|
data/lib/atlas_rb/person.rb
CHANGED
|
@@ -89,10 +89,14 @@ module AtlasRb
|
|
|
89
89
|
# @param on_behalf_of [String, nil] acting-as target (the acting principal
|
|
90
90
|
# itself comes from the ambient AtlasRb.config.default_nuid).
|
|
91
91
|
# @return [AtlasRb::Mash] the unwrapped `"person"` object.
|
|
92
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
93
|
+
# resource, so the write did not happen.
|
|
94
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
95
|
+
# and body.
|
|
92
96
|
def self.create(nuid:, display_name:, bio: nil, orcid: nil, title: nil, on_behalf_of: nil)
|
|
93
97
|
body = { nuid: nuid, display_name: display_name, bio: bio, orcid: orcid, title: title }.compact
|
|
94
|
-
AtlasRb::Mash.new(
|
|
95
|
-
connection({}, nil, on_behalf_of: on_behalf_of).post(ROUTE, JSON.dump(body))
|
|
98
|
+
AtlasRb::Mash.new(write_resource(
|
|
99
|
+
connection({}, nil, on_behalf_of: on_behalf_of).post(ROUTE, JSON.dump(body))
|
|
96
100
|
))["person"]
|
|
97
101
|
end
|
|
98
102
|
|
|
@@ -107,10 +111,14 @@ module AtlasRb
|
|
|
107
111
|
# @param nuid [String, nil] acting principal.
|
|
108
112
|
# @param on_behalf_of [String, nil] acting-as target.
|
|
109
113
|
# @return [AtlasRb::Mash] the unwrapped, updated `"person"` object.
|
|
114
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
115
|
+
# resource, so the write did not happen.
|
|
116
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
117
|
+
# and body.
|
|
110
118
|
def self.update(id, display_name: nil, bio: nil, orcid: nil, title: nil, nuid: nil, on_behalf_of: nil)
|
|
111
119
|
body = { display_name: display_name, bio: bio, orcid: orcid, title: title }.compact
|
|
112
|
-
AtlasRb::Mash.new(
|
|
113
|
-
connection({}, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, JSON.dump(body))
|
|
120
|
+
AtlasRb::Mash.new(write_resource(
|
|
121
|
+
connection({}, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, JSON.dump(body))
|
|
114
122
|
))["person"]
|
|
115
123
|
end
|
|
116
124
|
|
|
@@ -122,10 +130,14 @@ module AtlasRb
|
|
|
122
130
|
# @param on_behalf_of [String, nil] acting-as target.
|
|
123
131
|
# @return [AtlasRb::Mash] the unwrapped `"person"` object, with the updated
|
|
124
132
|
# `affiliated_community_ids`.
|
|
133
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
134
|
+
# resource, so the write did not happen.
|
|
135
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
136
|
+
# and body.
|
|
125
137
|
def self.add_affiliation(id, community_id, nuid: nil, on_behalf_of: nil)
|
|
126
|
-
AtlasRb::Mash.new(
|
|
138
|
+
AtlasRb::Mash.new(write_resource(
|
|
127
139
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
128
|
-
.post(ROUTE + id + "/affiliations", JSON.dump(community_id: community_id))
|
|
140
|
+
.post(ROUTE + id + "/affiliations", JSON.dump(community_id: community_id))
|
|
129
141
|
))["person"]
|
|
130
142
|
end
|
|
131
143
|
|
|
@@ -136,10 +148,14 @@ module AtlasRb
|
|
|
136
148
|
# @param nuid [String, nil] acting principal.
|
|
137
149
|
# @param on_behalf_of [String, nil] acting-as target.
|
|
138
150
|
# @return [AtlasRb::Mash] the unwrapped `"person"` object.
|
|
151
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
152
|
+
# resource, so the write did not happen.
|
|
153
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
154
|
+
# and body.
|
|
139
155
|
def self.remove_affiliation(id, community_id, nuid: nil, on_behalf_of: nil)
|
|
140
|
-
AtlasRb::Mash.new(
|
|
156
|
+
AtlasRb::Mash.new(write_resource(
|
|
141
157
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
142
|
-
.delete(ROUTE + id + "/affiliations/" + community_id)
|
|
158
|
+
.delete(ROUTE + id + "/affiliations/" + community_id)
|
|
143
159
|
))["person"]
|
|
144
160
|
end
|
|
145
161
|
end
|
data/lib/atlas_rb/resource.rb
CHANGED
|
@@ -368,5 +368,70 @@ module AtlasRb
|
|
|
368
368
|
JSON.parse(resp.body)
|
|
369
369
|
end
|
|
370
370
|
private_class_method :fetch_resource
|
|
371
|
+
|
|
372
|
+
# Shared write path behind the resource `POST` / `PATCH` / `DELETE`
|
|
373
|
+
# bindings: check the status, then parse. The companion to
|
|
374
|
+
# {fetch_resource}, and it exists for the same reason — Atlas answers a
|
|
375
|
+
# write aimed at a resource that isn't there with `head :not_found`, whose
|
|
376
|
+
# body is empty, so a bare `JSON.parse(resp.body)` raised
|
|
377
|
+
# `JSON::ParserError: unexpected end of input`. An operator loading a
|
|
378
|
+
# manifest of PIDs from another environment saw that, and nothing naming
|
|
379
|
+
# the missing object.
|
|
380
|
+
#
|
|
381
|
+
# Mapping:
|
|
382
|
+
#
|
|
383
|
+
# - `404` → {AtlasRb::NotFoundError}, naming the verb and path.
|
|
384
|
+
# - `410` → the parsed JSON body, as on the read path. An
|
|
385
|
+
# Idempotency-Key replay whose resource has since been tombstoned answers
|
|
386
|
+
# `410 Gone` WITH the tombstone, so it is a returnable body carrying
|
|
387
|
+
# `tombstoned` / `tombstoned_at` / `tombstoned_by`, not an error envelope.
|
|
388
|
+
# - any other non-2xx → {AtlasRb::ResourceError} carrying Atlas's status +
|
|
389
|
+
# body, so the failure is attributable at the boundary.
|
|
390
|
+
# - `2xx` → the parsed JSON body, for the caller to unwrap.
|
|
391
|
+
#
|
|
392
|
+
# Note the deliberate asymmetry with {fetch_resource}, which returns `nil`
|
|
393
|
+
# on a `404`: "there is nothing there" is a legitimate answer to a read,
|
|
394
|
+
# but not to a write. The caller asked for a change and did not get one, so
|
|
395
|
+
# `nil` would invite exactly the silent failure the read guard was written
|
|
396
|
+
# to prevent.
|
|
397
|
+
#
|
|
398
|
+
# The typed `403` / `422` translations ({AtlasRb::ForbiddenError},
|
|
399
|
+
# {AtlasRb::ReparentError}, and their siblings) fire in
|
|
400
|
+
# {Middleware::RaiseOnResourceError} while the request is still in the
|
|
401
|
+
# Faraday stack, so they raise before a binding reaches this — and a `422`
|
|
402
|
+
# the middleware deliberately passes through (`tombstone`'s
|
|
403
|
+
# `has_live_children`) reaches its caller as before, because the tombstone
|
|
404
|
+
# bindings return the raw response and never parse.
|
|
405
|
+
#
|
|
406
|
+
# @param resp [Faraday::Response] the completed write response.
|
|
407
|
+
# @return [Hash, Array] the parsed JSON body (incl. a `410` tombstone).
|
|
408
|
+
# @raise [AtlasRb::NotFoundError] on a `404`.
|
|
409
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx except `410`.
|
|
410
|
+
# @api private
|
|
411
|
+
def self.write_resource(resp)
|
|
412
|
+
if resp.status == 404
|
|
413
|
+
raise AtlasRb::NotFoundError.new("#{write_target(resp)} → 404 (no such resource)", response: resp)
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
unless resp.success? || resp.status == 410
|
|
417
|
+
raise AtlasRb::ResourceError.new("#{write_target(resp)} → #{resp.status}: #{resp.body}", response: resp)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
JSON.parse(resp.body)
|
|
421
|
+
end
|
|
422
|
+
private_class_method :write_resource
|
|
423
|
+
|
|
424
|
+
# The verb and path of a completed request — `"PATCH /works/abc123"` — so a
|
|
425
|
+
# {write_resource} failure names what did not happen. Read off the response
|
|
426
|
+
# rather than passed in, keeping every write binding a plain wrap.
|
|
427
|
+
#
|
|
428
|
+
# @param resp [Faraday::Response] the completed response.
|
|
429
|
+
# @return [String] the verb and path.
|
|
430
|
+
# @api private
|
|
431
|
+
def self.write_target(resp)
|
|
432
|
+
env = resp.env
|
|
433
|
+
"#{env&.method.to_s.upcase} #{env&.url&.path}"
|
|
434
|
+
end
|
|
435
|
+
private_class_method :write_target
|
|
371
436
|
end
|
|
372
437
|
end
|
data/lib/atlas_rb/work.rb
CHANGED
|
@@ -103,6 +103,10 @@ module AtlasRb
|
|
|
103
103
|
# setter on the update surface.
|
|
104
104
|
# @return [Hash] the created Work payload (post-update if `xml_path` was
|
|
105
105
|
# supplied).
|
|
106
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
107
|
+
# resource, so the write did not happen.
|
|
108
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
109
|
+
# and body.
|
|
106
110
|
#
|
|
107
111
|
# @example Empty work, metadata to be added later
|
|
108
112
|
# AtlasRb::Work.create("col-456")
|
|
@@ -120,9 +124,9 @@ module AtlasRb
|
|
|
120
124
|
on_behalf_of: nil, depositor: nil)
|
|
121
125
|
params = { collection_id: id }
|
|
122
126
|
params[:depositor] = depositor if depositor
|
|
123
|
-
result = AtlasRb::Mash.new(
|
|
127
|
+
result = AtlasRb::Mash.new(write_resource(
|
|
124
128
|
connection(params, nuid,
|
|
125
|
-
on_behalf_of: on_behalf_of, idempotency_key: idempotency_key).post(ROUTE)
|
|
129
|
+
on_behalf_of: on_behalf_of, idempotency_key: idempotency_key).post(ROUTE)
|
|
126
130
|
))["work"]
|
|
127
131
|
return result if xml_path.to_s.empty?
|
|
128
132
|
|
|
@@ -163,13 +167,17 @@ module AtlasRb
|
|
|
163
167
|
# envelope's `error` code is exposed as `#code`.
|
|
164
168
|
# @raise [AtlasRb::ForbiddenError] if Atlas refuses the move on
|
|
165
169
|
# authorization grounds (HTTP 403).
|
|
170
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
171
|
+
# resource, so the write did not happen.
|
|
172
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
173
|
+
# and body.
|
|
166
174
|
#
|
|
167
175
|
# @example
|
|
168
176
|
# AtlasRb::Work.reparent("w-789", "col-999")
|
|
169
177
|
def self.reparent(id, new_collection_id, nuid: nil, on_behalf_of: nil)
|
|
170
|
-
AtlasRb::Mash.new(
|
|
178
|
+
AtlasRb::Mash.new(write_resource(
|
|
171
179
|
connection({ parent_id: new_collection_id }, nuid, on_behalf_of: on_behalf_of)
|
|
172
|
-
.patch(ROUTE + id + '/parent')
|
|
180
|
+
.patch(ROUTE + id + '/parent')
|
|
173
181
|
))["work"]
|
|
174
182
|
end
|
|
175
183
|
|
|
@@ -235,6 +243,10 @@ module AtlasRb
|
|
|
235
243
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
236
244
|
# omitted.
|
|
237
245
|
# @return [Hash] the parsed JSON response from the patch.
|
|
246
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
247
|
+
# resource, so the write did not happen.
|
|
248
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
249
|
+
# and body.
|
|
238
250
|
#
|
|
239
251
|
# @example
|
|
240
252
|
# AtlasRb::Work.update("w-789", "/tmp/work-mods.xml")
|
|
@@ -242,8 +254,8 @@ module AtlasRb
|
|
|
242
254
|
payload = { binary: Faraday::Multipart::FilePart.new(File.open(xml_path),
|
|
243
255
|
"application/xml",
|
|
244
256
|
File.basename(xml_path)) }
|
|
245
|
-
AtlasRb::Mash.new(
|
|
246
|
-
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
257
|
+
AtlasRb::Mash.new(write_resource(
|
|
258
|
+
multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)
|
|
247
259
|
))
|
|
248
260
|
end
|
|
249
261
|
|
|
@@ -264,12 +276,16 @@ module AtlasRb
|
|
|
264
276
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
265
277
|
# omitted.
|
|
266
278
|
# @return [Hash] the parsed JSON response.
|
|
279
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
280
|
+
# resource, so the write did not happen.
|
|
281
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
282
|
+
# and body.
|
|
267
283
|
#
|
|
268
284
|
# @example
|
|
269
285
|
# AtlasRb::Work.metadata("w-789", title: "Revised Title")
|
|
270
286
|
def self.metadata(id, values, nuid: nil, on_behalf_of: nil)
|
|
271
|
-
AtlasRb::Mash.new(
|
|
272
|
-
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
287
|
+
AtlasRb::Mash.new(write_resource(
|
|
288
|
+
connection({ metadata: values }, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id)
|
|
273
289
|
))
|
|
274
290
|
end
|
|
275
291
|
|
|
@@ -293,6 +309,10 @@ module AtlasRb
|
|
|
293
309
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
294
310
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
295
311
|
# `error: "stale_resource"`).
|
|
312
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
313
|
+
# resource, so the write did not happen.
|
|
314
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
315
|
+
# and body.
|
|
296
316
|
#
|
|
297
317
|
# @example
|
|
298
318
|
# AtlasRb::Work.set_thumbnails(
|
|
@@ -303,9 +323,9 @@ module AtlasRb
|
|
|
303
323
|
# )
|
|
304
324
|
def self.set_thumbnails(id, thumbnail: nil, thumbnail_2x: nil, preview: nil, nuid: nil, on_behalf_of: nil)
|
|
305
325
|
body = { thumbnail: thumbnail, thumbnail_2x: thumbnail_2x, preview: preview }.compact
|
|
306
|
-
AtlasRb::Mash.new(
|
|
326
|
+
AtlasRb::Mash.new(write_resource(
|
|
307
327
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
308
|
-
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
328
|
+
.patch(ROUTE + id + '/thumbnails', JSON.dump(body))
|
|
309
329
|
))
|
|
310
330
|
end
|
|
311
331
|
|
|
@@ -329,6 +349,10 @@ module AtlasRb
|
|
|
329
349
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
330
350
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
331
351
|
# `error: "stale_resource"`).
|
|
352
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
353
|
+
# resource, so the write did not happen.
|
|
354
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
355
|
+
# and body.
|
|
332
356
|
#
|
|
333
357
|
# @example
|
|
334
358
|
# AtlasRb::Work.set_image_derivatives(
|
|
@@ -339,9 +363,9 @@ module AtlasRb
|
|
|
339
363
|
# )
|
|
340
364
|
def self.set_image_derivatives(id, small: nil, medium: nil, large: nil, nuid: nil, on_behalf_of: nil)
|
|
341
365
|
body = { small: small, medium: medium, large: large }.compact
|
|
342
|
-
AtlasRb::Mash.new(
|
|
366
|
+
AtlasRb::Mash.new(write_resource(
|
|
343
367
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
344
|
-
.patch(ROUTE + id + '/image_derivatives', JSON.dump(body))
|
|
368
|
+
.patch(ROUTE + id + '/image_derivatives', JSON.dump(body))
|
|
345
369
|
))
|
|
346
370
|
end
|
|
347
371
|
|
|
@@ -386,6 +410,10 @@ module AtlasRb
|
|
|
386
410
|
# (422) — `tier_exceeds_resource` / `tier_ordering_violation` /
|
|
387
411
|
# `unknown_tier` (see {#code}).
|
|
388
412
|
# @raise [AtlasRb::StaleResourceError] on an optimistic-lock conflict (409).
|
|
413
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
414
|
+
# resource, so the write did not happen.
|
|
415
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
416
|
+
# and body.
|
|
389
417
|
#
|
|
390
418
|
# @example
|
|
391
419
|
# AtlasRb::Work.set_derivative_permissions(
|
|
@@ -395,9 +423,9 @@ module AtlasRb
|
|
|
395
423
|
# service: ["northeastern:drs:repository:archives"] }
|
|
396
424
|
# )
|
|
397
425
|
def self.set_derivative_permissions(id, policy:, nuid: nil, on_behalf_of: nil)
|
|
398
|
-
AtlasRb::Mash.new(
|
|
426
|
+
AtlasRb::Mash.new(write_resource(
|
|
399
427
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
400
|
-
.patch(ROUTE + id + '/derivative_permissions', JSON.dump(policy))
|
|
428
|
+
.patch(ROUTE + id + '/derivative_permissions', JSON.dump(policy))
|
|
401
429
|
))
|
|
402
430
|
end
|
|
403
431
|
|
|
@@ -427,13 +455,17 @@ module AtlasRb
|
|
|
427
455
|
# @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
|
|
428
456
|
# conflict that exhausted its internal retry budget (HTTP 409 with
|
|
429
457
|
# `error: "stale_resource"`).
|
|
458
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
459
|
+
# resource, so the write did not happen.
|
|
460
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
461
|
+
# and body.
|
|
430
462
|
#
|
|
431
463
|
# @example
|
|
432
464
|
# AtlasRb::Work.set_full_text("w-789", text: extracted_pdf_text)
|
|
433
465
|
def self.set_full_text(id, text:, nuid: nil, on_behalf_of: nil)
|
|
434
|
-
AtlasRb::Mash.new(
|
|
466
|
+
AtlasRb::Mash.new(write_resource(
|
|
435
467
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
436
|
-
.patch(ROUTE + id + '/full_text', JSON.dump(text: text))
|
|
468
|
+
.patch(ROUTE + id + '/full_text', JSON.dump(text: text))
|
|
437
469
|
))
|
|
438
470
|
end
|
|
439
471
|
|
|
@@ -620,14 +652,18 @@ module AtlasRb
|
|
|
620
652
|
# as `#code`.
|
|
621
653
|
# @raise [AtlasRb::ForbiddenError] if Atlas refuses the link on
|
|
622
654
|
# authorization grounds (HTTP 403).
|
|
655
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
656
|
+
# resource, so the write did not happen.
|
|
657
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
658
|
+
# and body.
|
|
623
659
|
#
|
|
624
660
|
# @example
|
|
625
661
|
# AtlasRb::Work.add_linked_member("w-789", "col-456")
|
|
626
662
|
# # => ["col-456"]
|
|
627
663
|
def self.add_linked_member(work_id, collection_id, nuid: nil, on_behalf_of: nil)
|
|
628
|
-
|
|
664
|
+
write_resource(
|
|
629
665
|
connection({ collection_id: collection_id }, nuid, on_behalf_of: on_behalf_of)
|
|
630
|
-
.post(ROUTE + work_id + '/linked_members')
|
|
666
|
+
.post(ROUTE + work_id + '/linked_members')
|
|
631
667
|
)
|
|
632
668
|
end
|
|
633
669
|
|
|
@@ -658,14 +694,18 @@ module AtlasRb
|
|
|
658
694
|
# as `#code`.
|
|
659
695
|
# @raise [AtlasRb::ForbiddenError] if Atlas refuses the removal on
|
|
660
696
|
# authorization grounds (HTTP 403).
|
|
697
|
+
# @raise [AtlasRb::NotFoundError] if Atlas answers `404` — the id names no such
|
|
698
|
+
# resource, so the write did not happen.
|
|
699
|
+
# @raise [AtlasRb::ResourceError] on any other non-2xx, carrying Atlas's status
|
|
700
|
+
# and body.
|
|
661
701
|
#
|
|
662
702
|
# @example
|
|
663
703
|
# AtlasRb::Work.remove_linked_member("w-789", "col-456")
|
|
664
704
|
# # => []
|
|
665
705
|
def self.remove_linked_member(work_id, collection_id, nuid: nil, on_behalf_of: nil)
|
|
666
|
-
|
|
706
|
+
write_resource(
|
|
667
707
|
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
668
|
-
.delete(ROUTE + work_id + '/linked_members/' + collection_id)
|
|
708
|
+
.delete(ROUTE + work_id + '/linked_members/' + collection_id)
|
|
669
709
|
)
|
|
670
710
|
end
|
|
671
711
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: atlas_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cliff
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|