Class: AtlasRb::Middleware::RaiseOnResourceError

Inherits:
Faraday::Middleware
  • Object
show all
Defined in:
lib/atlas_rb/middleware/raise_on_resource_error.rb

Overview

Translates Atlas's structured re-parent / linked-member rejections into typed Ruby exceptions, so the resource bindings don't silently swallow the error envelope.

The re-parent and linked-member bindings unwrap their success payload by a fixed key (["collection"] / ["work"] / ["community"], or the bare linked-member array). On a 4xx that key is absent, so the binding would return nil and discard Atlas's machine-readable error / message. This middleware keys on the request path + status and raises a typed error carrying the envelope through, parallel to RaiseOnStaleResource.

It is intentionally narrow — it only fires on the re-parent (.../parent) and linked-member (.../linked_members...) write paths, and only on 403 / 422 bodies carrying an error discriminator. Everything else (other paths, other statuses, a 422 whose body uses a different discriminator such as tombstone's code: "has_live_children") passes through untouched, so atlas_rb stays a thin Faraday binding that translates only the wire signals callers genuinely need to discriminate.

Mapping:

Instance Method Summary collapse

Instance Method Details

#on_complete(env) ⇒ void

This method returns an undefined value.

Parameters:

  • env (Faraday::Env)

    the completed response environment.

Raises:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/atlas_rb/middleware/raise_on_resource_error.rb', line 35

def on_complete(env)
  return unless env.status == 403 || env.status == 422

  path     = env.url&.path.to_s
  reparent = path.end_with?("/parent")
  linked   = path.include?("/linked_members")
  return unless reparent || linked

  body = parse_json(env.body)
  return unless body.is_a?(Hash) && body["error"]

  if env.status == 403
    raise AtlasRb::ForbiddenError.new(
      body["message"] || "Atlas refused the request",
      code: body["error"],
      action: body["action"],
      subject: body["subject"]
    )
  elsif reparent
    raise AtlasRb::ReparentError.new(
      body["message"] || "Atlas rejected the re-parent",
      code: body["error"],
      resource_id: body["resource_id"]
    )
  else
    raise AtlasRb::LinkedMemberError.new(
      body["message"] || "Atlas rejected the linked-member write",
      code: body["error"],
      resource_id: body["resource_id"]
    )
  end
end