· 6 years ago · Sep 12, 2019, 10:42 AM
1module Api
2 class ApiApplicationController < ApplicationController
3 protect_from_forgery(with: :null_session)
4 respond_to(:json)
5 rescue_from(Exception, with: :handle_api_exception)
6 rescue_from(ActiveRecord::RecordNotFound, with: :api_not_found) unless Rails.env.development?
7 rescue_from(ActionController::RoutingError, with: :api_not_found) unless Rails.env.development?
8 abstract!
9
10 protected
11
12 # pass in a model class to ensure that all attributes in the returned hash are valid for the model.
13 def json_params(model = nil)
14 # we ignore ID, Created At, Updated At as they are set by the server side. Clients should not dictate these.
15 json_parameters = ActiveModelSerializers::Deserialization.jsonapi_parse(params, except: [:created_at, :updated_at, :id])
16 if !model.nil? && model.respond_to?(:column_names)
17 return json_parameters.delete_if {|key, value| !model.column_names.include?(key.to_s)}
18 end
19 json_parameters
20 end
21
22 def handle_api_model_failure(model)
23 return if model.nil? || !model.respond_to?(:errors)
24 warn("#{model.class.name} failed for method:#{request.method}:#{request.path} due to errors {#{model.errors.full_messages.join(' | ')}}")
25 render(json: model, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer, status: 400)
26 end
27
28 def api_not_found
29 error_obj = {
30 status: '404',
31 source: {
32 pointer: request.path
33 },
34 title: 'Resource not found',
35 detail: 'Resource at the given source is invalid'
36 }
37 render(json: {errors: [error_obj]}, status: 404)
38 end
39
40 def page_param
41 page_parameter = params.fetch(:page, {number: 1})
42 page_number = 1
43 if page_parameter.is_a?(Hash)
44 page_number = ActiveRecord::Type::Integer.new.type_cast_from_user((page_parameter['number'] || '1'))
45 elsif page_parameter.is_a?(String)
46 page_number = ActiveRecord::Type::Integer.new.type_cast_from_user((page_parameter || '1'))
47 end
48 [1, page_number].max
49 end
50
51 def page_size_param
52 page_parameter = params.fetch(:page, {size: 25})
53 if page_parameter.is_a?(Hash)
54 page_size = ActiveRecord::Type::Integer.new.type_cast_from_user((page_parameter['size'] || '25'))
55 else
56 page_parameter = params.fetch(:size, 25)
57 page_size = ActiveRecord::Type::Integer.new.type_cast_from_user(page_parameter)
58 end
59 [1, page_size].max
60 end
61
62 def paginate?
63 !params[:page].blank?
64 end
65
66 def handle_api_exception(exception)
67 fatal("Handling API Exception:#{exception}\n#{exception.backtrace.join("\n")}")
68 ExceptionNotifier.notify_exception(exception, env: request.env) unless Rails.env.development?
69 error_obj = {
70 status: '500',
71 source: {pointer: request.path},
72 title: exception.class.to_s,
73 detail: exception.to_s
74 }
75 error_obj[:backtrace] = exception.backtrace.take(10) unless Rails.env.production?
76 render(json: {errors: [error_obj]}, status: 500)
77 end
78
79 end
80end