Class: NucleusCore::Responder

Inherits:
Object
  • Object
show all
Defined in:
lib/nucleus_core/responder.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request_adapter: nil, response_adapter: nil) ⇒ Responder

Returns a new instance of Responder.



7
8
9
10
11
# File 'lib/nucleus_core/responder.rb', line 7

def initialize(request_adapter: nil, response_adapter: nil)
  @request_adapter = request_adapter
  @response_adapter = response_adapter
  @request_context = nil
end

Instance Attribute Details

#request_adapterObject

Returns the value of attribute request_adapter.



5
6
7
# File 'lib/nucleus_core/responder.rb', line 5

def request_adapter
  @request_adapter
end

#request_contextObject

Returns the value of attribute request_context.



5
6
7
# File 'lib/nucleus_core/responder.rb', line 5

def request_context
  @request_context
end

#response_adapterObject

Returns the value of attribute response_adapter.



5
6
7
# File 'lib/nucleus_core/responder.rb', line 5

def response_adapter
  @response_adapter
end

Instance Method Details

#exception_to_status(exception) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/nucleus_core/responder.rb', line 93

def exception_to_status(exception)
  exceptions = NucleusCore.configuration.exceptions

  case exception
  when NucleusCore::NotFound, *exceptions.not_found
    :not_found
  when NucleusCore::BadRequest, *exceptions.bad_request
    :bad_request
  when NucleusCore::NotAuthorized, *exceptions.forbidden
    :forbidden
  when NucleusCore::Unprocessable, *exceptions.unprocessable
    :unprocessable_entity
  else
    :internal_server_error
  end
end

#execute(raw_request_context = nil, &block) ⇒ Object

rubocop:disable Lint/RescueException:



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/nucleus_core/responder.rb', line 14

def execute(raw_request_context=nil, &block)
  return if block.nil?

  request_context_attrs = request_adapter&.call(raw_request_context) || {}
  @request_context = NucleusCore::RequestAdapter.new(request_context_attrs)
  entity = execute_block(@request_context, &block)

  render_entity(entity)
rescue Exception => e
  handle_exception(e)
end

#execute_block(request, &block) ⇒ Object

Calling ‘return` in a block/proc returns from the outer calling scope as well. Lambdas do not have this limitation. So we convert the proc returned from a block method into a lambda to avoid ’return’ exiting the method early. stackoverflow.com/questions/2946603/ruby-convert-proc-to-lambda



31
32
33
34
35
# File 'lib/nucleus_core/responder.rb', line 31

def execute_block(request, &block)
  define_singleton_method(:_proc_to_lambda_, &block)

  method(:_proc_to_lambda_).to_proc.call(request)
end

#handle_context(context) ⇒ Object



43
44
45
46
47
48
49
50
# File 'lib/nucleus_core/responder.rb', line 43

def handle_context(context)
  return render_nothing(context) if context.success?
  return handle_exception(context.exception) if context.exception

  view = NucleusCore::ErrorView.new(message: context.message, status: :unprocessable_entity)

  render_view(view)
end

#handle_exception(exception) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/nucleus_core/responder.rb', line 76

def handle_exception(exception)
  logger(exception)

  status = exception_to_status(exception)
  view = NucleusCore::ErrorView.new(message: exception.message, status: status)

  render_view(view)
end

#logger(object, log_level = :info) ⇒ Object



114
115
116
# File 'lib/nucleus_core/responder.rb', line 114

def logger(object, log_level=:info)
  NucleusCore.configuration.logger&.send(log_level, object)
end

#render_entity(entity) ⇒ Object



37
38
39
40
41
# File 'lib/nucleus_core/responder.rb', line 37

def render_entity(entity)
  return handle_context(entity) if entity.is_a?(NucleusCore::Operation::Context)
  return render_view(entity) if subclass_of(entity, NucleusCore::View)
  return render_response(entity) if subclass_of(entity, NucleusCore::ResponseAdapter)
end

#render_headers(headers = {}) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/nucleus_core/responder.rb', line 85

def render_headers(headers={})
  (headers || {}).each do |k, v|
    formatted_key = k.titleize.gsub(/\s *|_/, "-")

    response_adapter&.set_header(formatted_key, v)
  end
end

#render_response(entity) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/nucleus_core/responder.rb', line 61

def render_response(entity)
  render_headers(entity.headers)

  render_method = {
    NucleusCore::JsonResponse => :render_json,
    NucleusCore::XmlResponse => :render_xml,
    NucleusCore::PdfResponse => :render_pdf,
    NucleusCore::CsvResponse => :render_csv,
    NucleusCore::TextResponse => :render_text,
    NucleusCore::NoResponse => :render_nothing
  }.fetch(entity.class, nil)

  response_adapter&.send(render_method, entity)
end

#render_view(view) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/nucleus_core/responder.rb', line 52

def render_view(view)
  render_to_format = "#{request_context.format}_response".to_sym
  format_response = view.send(render_to_format) if view.respond_to?(render_to_format)

  raise NucleusCore::BadRequest, "`#{request_context.format}` is not supported" if format_response.nil?

  render_response(format_response)
end

#subclass_of(entity, *classes) ⇒ Object



110
111
112
# File 'lib/nucleus_core/responder.rb', line 110

def subclass_of(entity, *classes)
  Set[*entity.class.ancestors].intersect?(classes.to_set)
end