Search code examples
ruby-on-railsactive-model-serializersrails-api

I don't want to send stack trace errors in Rails API


I'm building a Rails 5 API and trying to handle the error response when a record is not found (i.e. /v1/users/99 but that user does not exist).

I'm using Active Model Serializer for serialization and I'm thinking there must be a way to only show the status and the error, not the stack trace. Right now, I get this:

{
status: 404,
error: "Not Found",
exception: "#<ActiveRecord::RecordNotFound: Couldn't find User with 'id'=99>",
traces: {
Application Trace: [
{
id: 1,
trace: "app/controllers/api/v1/users_controller.rb:45:in `set_user'"
}
],
Framework Trace: [
{
id: 0,
trace: "activerecord (5.0.2) lib/active_record/core.rb:173:in `find'"
},
{
id: 2,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:382:in `block in make_lambda'"
},
{
id: 3,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional'"
},
{
id: 4,
trace: "actionpack (5.0.2) lib/abstract_controller/callbacks.rb:12:in `block (2 levels) in <module:Callbacks>'"
},
{
id: 5,
trace: "activesupport (5.0.2) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'"
    },
.
.
.

I want the error to simple on the API side, just status and error. How can this be done?


Solution

  • I've been doing this for logging and printing different messages in different environments.

    class ApplicationController < ActionController::API
      rescue_from ActiveRecord::RecordNotFound, with: :record_not_found_rescue
    
      def record_not_found_rescue(exception)
        logger.info("#{exception.class}: " + exception.message)
        if Rails.env.production?
          render json: {}, status: :not_found
        else
          render json: { message: exception, backtrace: exception.backtrace }, status: :not_found
        end
      end
    end
    

    I found this to be useful not only to not print back traces but you now don't need an if statement in every single controller action.

    It couples well with finder methods in your controller.

      def show
        user = find_user
    
        render json: user , status: :ok
      end
    
      private
        def find_user
          User.find(params[:id])
        end
    

    Remember you can handle different types of exceptions like this, not only the ActiveRecord::RecordNotFound.