Module: ActionFigure::ErrorRegistry

Included in:
ActionFigure
Defined in:
lib/action_figure/error_registry.rb,
sig/action_figure.rbs

Overview

Central registry of error-helper name → status symbol mappings.

Defined Under Namespace

Modules: Helpers

Constant Summary collapse

DEFAULTS =

Built-in error statuses. Domain-owned 4xx only — no 5xx ships built-in.

Returns:

  • (Hash[Symbol, Symbol])
{
  UnprocessableContent: :unprocessable_content,
  NotFound: :not_found,
  Forbidden: :forbidden,
  Conflict: :conflict,
  PaymentRequired: :payment_required,
  Gone: :gone,
  Locked: :locked,
  UnavailableForLegalReasons: :unavailable_for_legal_reasons
}.freeze
STATUS_CODE_FALLBACKS =

Statuses Rack itself doesn't map on every supported version: Rack < 3.1 knows 422 only as :unprocessable_entity, Rack >= 3.1 only as :unprocessable_content. Accept both everywhere.

Returns:

  • (Hash[Symbol, Integer])
{ unprocessable_content: 422, unprocessable_entity: 422 }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_helper(name, status_symbol) ⇒ void

This method returns an undefined value.

Parameters:

  • name (Symbol)
  • status_symbol (Symbol)


34
35
36
37
38
# File 'lib/action_figure/error_registry.rb', line 34

def self.define_helper(name, status_symbol)
  Helpers.define_method(name) do |errors: nil, **extras|
    error_response(errors: errors, status: status_symbol, **extras)
  end
end

.extended(base) ⇒ Object

Populates the registry when ErrorRegistry is extended (at gem load, single-threaded), so no lazy initialization races with reader threads.



44
45
46
47
48
# File 'lib/action_figure/error_registry.rb', line 44

def self.extended(base)
  registry = Concurrent::Map.new
  DEFAULTS.each { |name, status| registry[name] = status }
  base.instance_variable_set(:@error_status_registry, registry)
end

Instance Method Details

#error_statusesHash[Symbol, Symbol]

A plain-Hash copy of the current registry (built-ins plus any registered).

Returns:

  • (Hash[Symbol, Symbol])


56
57
58
# File 'lib/action_figure/error_registry.rb', line 56

def error_statuses
  error_status_registry.each_pair.to_h
end

#register_error(name, status_symbol) ⇒ Symbol

Registers an additional error status. Add-only: does not remove or override. Defines the generated helper on the live Helpers module (so it appears on every formatter and already-included action class immediately) and patches already-loaded test adapters.

Parameters:

  • name (Symbol, String)
  • status_symbol (Symbol, String)

Returns:

  • (Symbol)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/action_figure/error_registry.rb', line 73

def register_error(name, status_symbol)
  name = name.to_sym
  status_symbol = status_symbol.to_sym
  validate_registration!(name, status_symbol)

  existing = error_status_registry.put_if_absent(name, status_symbol)
  if existing && existing != status_symbol
    raise ArgumentError,
          "Error status #{name.inspect} is already registered as #{existing.inspect}; " \
          "register_error is add-only and cannot override it"
  end
  return name if existing

  ErrorRegistry.define_helper(name, status_symbol)
  ActionFigure::Testing.define_error_helper(name, status_symbol) if defined?(ActionFigure::Testing)
  name
end

#status_code_for(status_symbol) ⇒ Integer

Resolves a Rack-style status symbol to its numeric HTTP status code, raising ArgumentError for symbols no supported Rack version knows. Single resolution point for formatters and register_error validation.

Parameters:

  • status_symbol (Symbol)

Returns:

  • (Integer)


63
64
65
66
67
# File 'lib/action_figure/error_registry.rb', line 63

def status_code_for(status_symbol)
  Rack::Utils::SYMBOL_TO_STATUS_CODE[status_symbol] ||
    STATUS_CODE_FALLBACKS[status_symbol] ||
    raise(ArgumentError, "#{status_symbol.inspect} is not a known HTTP status symbol")
end