Class: ApiBlocks::Responder

Inherits:
ActionController::Responder
  • Object
show all
Includes:
Responders::HttpCacheResponder
Defined in:
lib/api_blocks/responder.rb

Overview

ApiBlocks::Responder provides a responder with better error handling and ‘ApiBlocks::Interactor` through `Dry::Monads::Result` support.

Instance Method Summary collapse

Instance Method Details

#api_behaviorObject

Override ActionController::Responder#api_behavior in order to provide one that matches our API documentation.

The only difference so far is that on POST we do not render ‘status: :created` along with a `Location` header.

Moreover, we display the resource on PUT.

Raises:

  • (MissingRenderer)


74
75
76
77
78
79
80
81
82
# File 'lib/api_blocks/responder.rb', line 74

def api_behavior
  raise(MissingRenderer, format) unless has_renderer?

  if get? || post? || put?
    display resource
  else
    head :no_content
  end
end

#display_errorsObject

Display is just a shortcut to render a resource’s errors with the current format using ‘problem_details` when format is set to JSON.



32
33
34
35
36
37
38
# File 'lib/api_blocks/responder.rb', line 32

def display_errors
  return super unless format == :json

  errors, status = resource_errors

  controller.render problem: errors, status: status
end

#has_errors?Boolean

rubocop:disable Naming/PredicateName

Returns:

  • (Boolean)


60
61
62
63
64
# File 'lib/api_blocks/responder.rb', line 60

def has_errors? # rubocop:disable Naming/PredicateName
  return true if @failure

  super
end

#resource_errorsObject

Override resource_errors to handle more error kinds and return a status code.



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/api_blocks/responder.rb', line 16

def resource_errors
  case @resource
  when ApplicationRecord
    [{ errors: @resource.errors }, :unprocessable_entity]
  when ActiveRecord::RecordInvalid
    [{ errors: @resource.record.errors }, :unprocessable_entity]
  else
    # propagate the error so it can be handled through the standard rails
    # error handlers.
    raise @resource
  end
end

#to_formatObject

All other formats follow the procedure below. First we try to render a template, if the template is not available, we verify if the resource responds to :to_format and display it.

In addition, if the resource is a Dry::Monads::Result we unwrap it and assign the failure instead.



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/api_blocks/responder.rb', line 47

def to_format
  return super unless resource.is_a?(Dry::Monads::Result)

  # unwrap the result monad so it can be processed by
  # ActionController::Responder
  resource.fmap { |result| @resource = result }.or do |failure|
    @resource = failure
    @failure = true
  end

  super
end