Skip to content

Instantly share code, notes, and snippets.

@RomanTurner
Last active July 13, 2022 04:37
Show Gist options
  • Save RomanTurner/c1c07b3542833bc13d1b2f62d49cae0a to your computer and use it in GitHub Desktop.
Save RomanTurner/c1c07b3542833bc13d1b2f62d49cae0a to your computer and use it in GitHub Desktop.
Error Serializer
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