Class: Cuprum::Rails::Responders::JsonResponder

Inherits:
BaseResponder show all
Includes:
Actions, Matching, Serialization
Defined in:
lib/cuprum/rails/responders/json_responder.rb

Overview

Provides a DSL for defining responses to JSON requests.

By default, responds to any successful result by serializing the result value and generating a JSON object of the form { ‘ok’ => true, ‘data’ => serialized_value }.

For a failing result, it generates and serializes a generic error and generates a JSON object of the form { ‘ok’ => false, ‘data’ => serialized_error }. This is to prevent leaks of internal states that might help an adversary access your system. Use the .match class method to define more useful responses for whitelisted errors.

Examples:

Defining Error Responses

class CustomResponder < Cuprum::Rails::Responders::HtmlResponder
  match :failure, error: Spec::NotFound do |result|
    render_failure(result.error, status: 404)
  end

  match :failure, error: Spec::AuthorizationFailure do
    error = Cuprum::Error.new(message: "I can't let you do that, Dave")

    render_failure(error, status: 403)
  end
end

Instance Attribute Summary

Attributes included from Serialization

#serializers

Attributes included from Matching

#matcher

Attributes inherited from BaseResponder

#action_name, #controller, #controller_name, #request, #resource, #result

Instance Method Summary collapse

Methods included from Serialization

#serialize

Methods included from Actions

included

Methods included from Matching

#member_action?

Methods inherited from BaseResponder

#member_action?, #routes

Constructor Details

#initialize(action_name:, controller:, request:, serializers:, member_action: false, **options) ⇒ JsonResponder

Returns a new instance of JsonResponder.

Parameters:

  • action_name (String, Symbol)

    the name of the action to match.

  • controller (Cuprum::Rails::Controller)

    the called controller.

  • controller_name (String)

    the name of the called controller. Defaults to controller.class.name.

  • matcher (Cuprum::Matcher)

    an optional matcher specific to the action. This will be matched before any of the generic matchers.

  • member_action (Boolean) (defaults to: false)

    true if the action acts on a collection item, not on the collection as a whole.

  • request (Cuprum::Rails::Request)

    the request to the controller.

  • serializers (Hash<Class, Object>)

    the serializers for converting result values into serialized data.

  • options (Hash)

    additional parameters for the responder.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/cuprum/rails/responders/json_responder.rb', line 67

def initialize( # rubocop:disable Metrics/ParameterLists
  action_name:,
  controller:,
  request:,
  serializers:,
  member_action: false,
  **options
)
  super(
    action_name:   action_name,
    controller:    controller,
    matcher:       matcher,
    member_action: member_action,
    resource:      resource,
    request:       request,
    serializers:   serializers,
    **options
  )
end

Instance Method Details

#call(result) ⇒ #call

Finds and calls the response clause that matches the given result.

  1. Checks for an exact match (the result status, value, and error all match) in the given matcher (if any), then the responder class, then each ancestor of the responder class in ascending order.

  2. If a match is not found, checks for a partial match (the result status, and either the value or the error match) in the same order.

  3. If there is still no match found, checks for a generic match (the result status matches, and the match clause does not specify either an error or a value.

  4. If there is no matching response clause, raises an exception.

If the responder defines an action matcher that matches the given action name, that matcher is matched against the result before any match clauses defined directly on the responder.

Parameters:

  • result (Cuprum::Result)

    the result of the action call.

Returns:

  • (#call)

    the response object from the matching response clause.

Raises:

  • (Cuprum::Matching::NoMatchError)

    if none of the response clauses match the result.



# File 'lib/cuprum/rails/responders/json_responder.rb', line 87

#formatSymbol

Returns the format of the responder.

Returns:

  • (Symbol)

    the format of the responder.



91
92
93
# File 'lib/cuprum/rails/responders/json_responder.rb', line 91

def format
  :json
end

#generic_errorCuprum::Error

Returns a generic error for generating failure responses.

Returns:

  • (Cuprum::Error)

    a generic error for generating failure responses.



96
97
98
# File 'lib/cuprum/rails/responders/json_responder.rb', line 96

def generic_error
  GENERIC_ERROR
end

#render(json, status: 200) ⇒ Cuprum::Rails::Responses::JsonResponse

Creates a JsonResponse based on the given data and options.

Parameters:

  • json (Object)

    The data to serialize.

  • status (Integer) (defaults to: 200)

    The HTTP status of the response.

Returns:



106
107
108
109
110
111
# File 'lib/cuprum/rails/responders/json_responder.rb', line 106

def render(json, status: 200)
  Cuprum::Rails::Responses::JsonResponse.new(
    data:   serialize(json),
    status: status
  )
end

#render_failure(error, status: 500) ⇒ Cuprum::Rails::Responses::JsonResponse

Creates a JsonResponse for a failed result.

Parameters:

  • error (Cuprum::Error)

    The error from the failed result.

  • status (Integer) (defaults to: 500)

    The HTTP status of the response.

Returns:



119
120
121
122
123
# File 'lib/cuprum/rails/responders/json_responder.rb', line 119

def render_failure(error, status: 500)
  json = { 'ok' => false, 'error' => error }

  render(json, status: status)
end

#render_success(value, status: 200) ⇒ Cuprum::Rails::Responses::JsonResponse

Creates a JsonResponse for a successful result.

Parameters:

  • value (Object)

    The value of the successful result.

  • status (Integer) (defaults to: 200)

    The HTTP status of the response.

Returns:



131
132
133
134
135
# File 'lib/cuprum/rails/responders/json_responder.rb', line 131

def render_success(value, status: 200)
  json = { 'ok' => true, 'data' => value }

  render(json, status: status)
end