ck3g
ck3g

Reputation: 5929

Handling ActiveRecord::RecordNotFound with ActionController::Metal

I'm on the developing (JSON) API stage and decide to inherit my ApiController from ActionController::Metal to took advantages of speed etc.

So I've included a bunch of modules to make it work.

Recently I've decide to respond with empty result when record not found. Rails already throws ActiveRecord::RecordNotFound from Model#find method and I've been trying to use rescue_from to catch it and write something like this:

module Api::V1
  class ApiController < ActionController::Metal
    # bunch of included modules 

    include ActiveSupport::Rescuable

    respond_to :json

    rescue_from ActiveRecord::RecordNotFound do
      binding.pry
      respond_to do |format|
        format.any { head :not_found }
      end
    end
  end
end  

After call my simple action

def show
  @post = Post.find(params[:id])
end

And execution never reach rescue_from. It's throws:

ActiveRecord::RecordNotFound (Couldn't find Post with id=1

into my log file.

I've been trying it and in production mode. Server responds with 404 but response body is standard HTML error page for JSON request.

It's works well when I change inheritance from ActionController::Metal to ActionController::Base.

You may notice about lack of respond_with call. That's because I'm using RABL as my template system.

So the question is: Is there any chances to make rescue_from work with Metal or get rid HTML from response?

Upvotes: 3

Views: 1404

Answers (1)

TJ Singleton
TJ Singleton

Reputation: 770

The following worked for me:

class ApiController < ActionController::Metal
  include ActionController::Rendering
  include ActionController::MimeResponds
  include ActionController::Rescue

  append_view_path Rails.root.join('app', 'views').to_s
  rescue_from ActiveRecord::RecordNotFound, with: :four_oh_four

  def four_oh_four
    render file: Rails.root.join("public", "404.html"), status: 404
  end
end

Upvotes: 6

Related Questions