Last active
July 13, 2022 04:37
-
-
Save RomanTurner/c1c07b3542833bc13d1b2f62d49cae0a to your computer and use it in GitHub Desktop.
Error Serializer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ErrorSerializer | |
attr_accessor :request, :params, :errors | |
def initialize(request, params, errors = [], exception = nil) | |
@request = request | |
@params = params | |
@errors = errors | |
@exception = exception | |
end | |
def serialize | |
{ | |
errors: | |
@errors.map do |error| | |
{ | |
id: @params[:id], | |
status: error[:status], | |
title: error[:title], | |
message: error[:message], | |
source: @request.parameters.merge({ url: @request.url }), | |
} | |
end, | |
}.to_json | |
end | |
def not_found | |
@errors = [ | |
{ | |
status: :not_found, | |
message: @exception, | |
title: 'ActiveRecord::RecordNotFound', | |
}, | |
] | |
serialize | |
end | |
def conflict | |
@errors = [ | |
{ | |
status: :conflict, | |
message: "Lead already scanned for attendee #{@params[:id]}", | |
exception: @exception, | |
title: 'ActiveRecord::RecordNotUnique', | |
}, | |
] | |
serialize | |
end | |
def unprocessable_entity | |
@errors = [ | |
{ | |
status: :unprocessable_entity, | |
message: @exception, | |
title: 'ActiveRecord::RecordInvalid', | |
}, | |
] | |
serialize | |
end | |
end | |
# Example Use Case | |
# | |
# I was looking specifically for certain validation errors to send back detailed error | |
# messages to the api user. Could expand to contain Model.errors.full_messages but I wanted to follow the spec closer. | |
# | |
class Api::V3::LeadsController < Api::BaseController | |
include RegHost | |
before_action :set_attendee, only: %i[show create update] | |
before_action :set_registration, only: %i[show create update] | |
before_action :set_lead, only: %i[update] | |
def index | |
render json: LeadsSerializer.new(@user.leads), status: :accepted | |
end | |
def show | |
render json: RegistrationSerializer.new(@registration), status: :accepted | |
end | |
# Setting the attendee is included in the RegHost concern | |
def create | |
begin | |
@user.leads.create( | |
event_exhibitor: @user.event_exhibitor, | |
registration: @registration, | |
) | |
render json: RegistrationSerializer.new(@registration), status: :created | |
rescue ActiveRecord::RecordNotUnique => exception | |
render json: ErrorSerializer.new(request, params, [], exception).conflict, | |
status: :conflict | |
end | |
end | |
def update | |
@lead.note.destroy if @lead.note.present? | |
@lead.responses.destroy_all unless @lead.responses.blank? | |
begin | |
@lead.update!(lead_params) | |
AddLeadToQualifierListJob.perform_later(@lead.id) | |
render json: LeadsSerializer.new(@lead), status: :accepted | |
rescue ActiveRecord::RecordInvalid => exception | |
invalid_record(exception) | |
rescue ActiveRecord::RecordNotFound => exception | |
not_found(exception) | |
end | |
end | |
private | |
def lead_params | |
params | |
.require(:lead) | |
.permit( | |
note_attributes: :body, | |
answers_attributes: %i[question_id body], | |
responses_attributes: [:answer_id], | |
qualifier_ids: [], | |
) | |
end | |
def set_lead | |
@lead = | |
Lead.find_or_create_by!( | |
registration: @registration, | |
user: @user, | |
event_exhibitor: @user.event_exhibitor, | |
) | |
rescue ActiveRecord::RecordNotFound => exception | |
not_found(exception) | |
rescue ActiveRecord::RecordNotUnique => exception | |
render json: ErrorSerializer.new(request, params, [], exception).conflict, | |
status: :conflict | |
end | |
def set_registration | |
@registration = | |
Registration.find_or_create_by!(event: @event, attendee: @attendee) | |
rescue ActiveRecord::RecordNotFound => exception | |
not_found(exception) | |
rescue ActiveRecord::RecordInvalid => exception | |
invalid_record(exception) | |
end | |
def not_found(exception) | |
render json: ErrorSerializer.new(request, params, [], exception).not_found, | |
status: :not_found | |
end | |
def invalid_record(exception) | |
render json: | |
ErrorSerializer.new(request, params, [], exception) | |
.unprocessable_entity, | |
status: :unprocessable_entity | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment