Application controller refactoring: Moving error methods to proper concern.
This commit is contained in:
parent
b82b183863
commit
f511995ba6
2 changed files with 83 additions and 95 deletions
|
@ -2,6 +2,8 @@
|
||||||
require 'exceptions'
|
require 'exceptions'
|
||||||
|
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
|
include ErrorHandling
|
||||||
|
|
||||||
# http_basic_authenticate_with :name => "test", :password => "ttt"
|
# http_basic_authenticate_with :name => "test", :password => "ttt"
|
||||||
|
|
||||||
helper_method :current_user,
|
helper_method :current_user,
|
||||||
|
@ -18,15 +20,6 @@ class ApplicationController < ActionController::Base
|
||||||
before_action :transaction_begin, :set_user, :session_update, :user_device_check, :cors_preflight_check
|
before_action :transaction_begin, :set_user, :session_update, :user_device_check, :cors_preflight_check
|
||||||
after_action :transaction_end, :http_log, :set_access_control_headers
|
after_action :transaction_end, :http_log, :set_access_control_headers
|
||||||
|
|
||||||
rescue_from StandardError, with: :server_error
|
|
||||||
rescue_from ExecJS::RuntimeError, with: :server_error
|
|
||||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
|
||||||
rescue_from ActiveRecord::StatementInvalid, with: :unprocessable_entity
|
|
||||||
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity
|
|
||||||
rescue_from ArgumentError, with: :unprocessable_entity
|
|
||||||
rescue_from Exceptions::UnprocessableEntity, with: :unprocessable_entity
|
|
||||||
rescue_from Exceptions::NotAuthorized, with: :unauthorized
|
|
||||||
|
|
||||||
# For all responses in this controller, return the CORS access control headers.
|
# For all responses in this controller, return the CORS access control headers.
|
||||||
def set_access_control_headers
|
def set_access_control_headers
|
||||||
headers['Access-Control-Allow-Origin'] = '*'
|
headers['Access-Control-Allow-Origin'] = '*'
|
||||||
|
@ -658,30 +651,6 @@ class ApplicationController < ActionController::Base
|
||||||
render json: generic_objects, status: :ok
|
render json: generic_objects, status: :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_match_error(error)
|
|
||||||
data = {
|
|
||||||
error: error
|
|
||||||
}
|
|
||||||
if error =~ /Validation failed: (.+?)(,|$)/i
|
|
||||||
data[:error_human] = $1
|
|
||||||
end
|
|
||||||
if error =~ /(already exists|duplicate key|duplicate entry)/i
|
|
||||||
data[:error_human] = 'Object already exists!'
|
|
||||||
end
|
|
||||||
if error =~ /null value in column "(.+?)" violates not-null constraint/i
|
|
||||||
data[:error_human] = "Attribute '#{$1}' required!"
|
|
||||||
end
|
|
||||||
if error =~ /Field '(.+?)' doesn't have a default value/i
|
|
||||||
data[:error_human] = "Attribute '#{$1}' required!"
|
|
||||||
end
|
|
||||||
|
|
||||||
if Rails.env.production? && !data[:error_human].empty?
|
|
||||||
data[:error] = data[:error_human]
|
|
||||||
data.delete('error_human')
|
|
||||||
end
|
|
||||||
data
|
|
||||||
end
|
|
||||||
|
|
||||||
def model_references_check(object, params)
|
def model_references_check(object, params)
|
||||||
generic_object = object.find(params[:id])
|
generic_object = object.find(params[:id])
|
||||||
result = Models.references(object, generic_object.id)
|
result = Models.references(object, generic_object.id)
|
||||||
|
@ -691,68 +660,6 @@ class ApplicationController < ActionController::Base
|
||||||
raise Exceptions::UnprocessableEntity, e
|
raise Exceptions::UnprocessableEntity, e
|
||||||
end
|
end
|
||||||
|
|
||||||
def not_found(e)
|
|
||||||
logger.error e.message
|
|
||||||
logger.error e.backtrace.inspect
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: model_match_error(e.message), status: :not_found }
|
|
||||||
format.any {
|
|
||||||
@exception = e
|
|
||||||
@traceback = !Rails.env.production?
|
|
||||||
file = File.open(Rails.root.join('public', '404.html'), 'r')
|
|
||||||
render inline: file.read, status: :not_found
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unprocessable_entity(e)
|
|
||||||
logger.error e.message
|
|
||||||
logger.error e.backtrace.inspect
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: model_match_error(e.message), status: :unprocessable_entity }
|
|
||||||
format.any {
|
|
||||||
@exception = e
|
|
||||||
@traceback = !Rails.env.production?
|
|
||||||
file = File.open(Rails.root.join('public', '422.html'), 'r')
|
|
||||||
render inline: file.read, status: :unprocessable_entity
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_error(e)
|
|
||||||
logger.error e.message
|
|
||||||
logger.error e.backtrace.inspect
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: model_match_error(e.message), status: 500 }
|
|
||||||
format.any {
|
|
||||||
@exception = e
|
|
||||||
@traceback = !Rails.env.production?
|
|
||||||
file = File.open(Rails.root.join('public', '500.html'), 'r')
|
|
||||||
render inline: file.read, status: 500
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unauthorized(e)
|
|
||||||
message = e.message
|
|
||||||
if message == 'Exceptions::NotAuthorized'
|
|
||||||
message = 'Not authorized'
|
|
||||||
end
|
|
||||||
error = model_match_error(message)
|
|
||||||
if error && error[:error]
|
|
||||||
response.headers['X-Failure'] = error[:error_human] || error[:error]
|
|
||||||
end
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: error, status: :unauthorized }
|
|
||||||
format.any {
|
|
||||||
@exception = e
|
|
||||||
@traceback = !Rails.env.production?
|
|
||||||
file = File.open(Rails.root.join('public', '401.html'), 'r')
|
|
||||||
render inline: file.read, status: :unauthorized
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# check maintenance mode
|
# check maintenance mode
|
||||||
def check_maintenance_only(user)
|
def check_maintenance_only(user)
|
||||||
return false if Setting.get('maintenance_mode') != true
|
return false if Setting.get('maintenance_mode') != true
|
||||||
|
|
81
app/controllers/concerns/error_handling.rb
Normal file
81
app/controllers/concerns/error_handling.rb
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
module ErrorHandling
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
rescue_from StandardError, with: :internal_server_error
|
||||||
|
rescue_from ExecJS::RuntimeError, with: :internal_server_error
|
||||||
|
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||||
|
rescue_from ActiveRecord::StatementInvalid, with: :unprocessable_entity
|
||||||
|
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity
|
||||||
|
rescue_from ArgumentError, with: :unprocessable_entity
|
||||||
|
rescue_from Exceptions::UnprocessableEntity, with: :unprocessable_entity
|
||||||
|
rescue_from Exceptions::NotAuthorized, with: :unauthorized
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_found(e)
|
||||||
|
log_error_exception(e)
|
||||||
|
respond_to_exception(e, :not_found)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unprocessable_entity(e)
|
||||||
|
log_error_exception(e)
|
||||||
|
respond_to_exception(e, :unprocessable_entity)
|
||||||
|
end
|
||||||
|
|
||||||
|
def internal_server_error(e)
|
||||||
|
log_error_exception(e)
|
||||||
|
respond_to_exception(e, :internal_server_error)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unauthorized(e)
|
||||||
|
error = humanize_error(e.message)
|
||||||
|
response.headers['X-Failure'] = error.fetch(:error_human, error[:error])
|
||||||
|
respond_to_exception(e, :unauthorized)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def log_error_exception(e)
|
||||||
|
logger.error e.message
|
||||||
|
logger.error e.backtrace.inspect
|
||||||
|
end
|
||||||
|
|
||||||
|
def respond_to_exception(e, status)
|
||||||
|
status_code = Rack::Utils.status_code(status)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render json: humanize_error(e.message), status: status }
|
||||||
|
format.any {
|
||||||
|
@exception = e
|
||||||
|
@traceback = !Rails.env.production?
|
||||||
|
file = File.open(Rails.root.join('public', "#{status_code}.html"), 'r')
|
||||||
|
render inline: file.read, status: status
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def humanize_error(error)
|
||||||
|
data = {
|
||||||
|
error: error
|
||||||
|
}
|
||||||
|
|
||||||
|
case error
|
||||||
|
when /Validation failed: (.+?)(,|$)/i
|
||||||
|
data[:error_human] = $1
|
||||||
|
when /(already exists|duplicate key|duplicate entry)/i
|
||||||
|
data[:error_human] = 'Object already exists!'
|
||||||
|
when /null value in column "(.+?)" violates not-null constraint/i
|
||||||
|
data[:error_human] = "Attribute '#{$1}' required!"
|
||||||
|
when /Field '(.+?)' doesn't have a default value/i
|
||||||
|
data[:error_human] = "Attribute '#{$1}' required!"
|
||||||
|
when 'Exceptions::NotAuthorized'
|
||||||
|
data[:error] = 'Not authorized'
|
||||||
|
data[:error_human] = data[:error]
|
||||||
|
end
|
||||||
|
|
||||||
|
if Rails.env.production? && !data[:error_human].empty?
|
||||||
|
data[:error] = data.delete(:error_human)
|
||||||
|
end
|
||||||
|
data
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue