Amanda Ferrari
Amanda Ferrari

Reputation: 946

How to return 404 when resource is not found, instead of HTML

I have this controller:

# frozen_string_literal: true

class MetricsController < ApplicationController
  before_action :set_post, only: [:update]

  def update
    if @post.update(post_params)
      render json: @post
    else
      render json: @post.errors, status: :unprocessable_entity
    end
  end

  private

  def set_post
    @post = Post.find_by(site: params[:site_id], post_id: params[:post_id])
  end

  def post_params
    params.fetch(:post, {})
  end
end

And I would like to know how can I return 404 not found when @post is nil. Right now @post.update raises an error if @post is nil, and the response is a HTML.

Upvotes: 0

Views: 419

Answers (3)

Diego Toral
Diego Toral

Reputation: 86

You could make use of ActiveRecord::FinderMethods#find_by! which raises an ActiveRecord::RecordNotFound instead of nil when the record isn't found, and then use a rescue_from block to handle the error.

class MetricsController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound do |exception|
    # it is up to you create RecordNotFoundSerializer
    serializer = RecordNotFoundSerializer.new exception

    render json: serializer.to_json, status: :not_found
  end

  private

  def set_post
    @post = Post.find_by(site: params[:site_id], post_id: params[:post_id])
  end
end

You can also extract the error handling to a base controller (ApplicationController in you example) and centralize error handling there.

Upvotes: 2

Sumanth Madishetty
Sumanth Madishetty

Reputation: 3605

You can add a check and return not_found if @post is nil & inorder to prevent your app from crashing you can handle other errors by adding rescue block and return your desired from there

def update
 return render json: YOUR_ERROR, status: :not_found unless @post
 if @post.update(post_params)
   render json: @post
 else
   render json: @post.errors, status: :unprocessable_entity
 end
rescue StandardError => e
  render json: e, status: :unprocessable_entity
end

Upvotes: 1

calebkm
calebkm

Reputation: 1033

You can add a check for @post to your controller action and return a 404 if it's nil:

def update
  if @post
    if @post.update(post_params)
      render json: @post
    else
      render json: @post.errors, status: :unprocessable_entity
    end
  else
    render json: YourCustomJsonError, status: 404
  end
end

Upvotes: 0

Related Questions