6

So, I am writing Rails web application which has JSON API for mobile apps. For example, it sends POST JSON request to example.com/api/orders to create order.

{id: 1, order: { product_name: "Pizza", price: 10000}}

In case of validation errors I can response with HTTP 422 error code and order.errors.full_messages in json. But it seems better for me to have specific error code in JSON response. Unfortunately, it seems like Rails does not provide ability to set error code for validation error. How to solve this problem?

1

3 Answers 3

6

You can pass a custom status code by using the status option when rendering the response.

def create
  @order = ...

  if @order.save
    render json: @order
  else
    render json: { message: "Validation failed", errors: @order.errors }, status: 400
  end
end

I usually tend to return HTTP 400 on validation errors. The message is a readable status response, the errors are also attached.

This is a respons example

{
    message: "Validation failed",
    errors: [
        ...
    ]
}

You can also embed additional attributes.

Sign up to request clarification or add additional context in comments.

4 Comments

This is just example with typo. The question is: how to add error codes to validation errors in Rails?
Thanks. But I want to do something different. I want to associate each kind of validation errors with unique error code which will be placed in JSON response body. {error_code: 50, error_message: "Email can not be blank"}, for example.
It's not hard to do what you want starting from my suggestion. Try to work on some code, don't expect an answer to provide copy/paste code.
I think the question was more about how to provide a unique code per validation message. As the error text can change per translation, if you're wanting to react clientside you can't use that. As such, it seems the answer is no, there is no way to add a unique errorcode per validation within rails.
1

I was after something similar, so what I did was extend String eg

class ErrorCodeString < String
  def init(value, error_code)
     @error_code = error_code
     super(value)
  end

  def error_code
      @error_code
  end
end

Then in a custom validation (this won't work on standard validation) I'd do

 errors.add(:email, ErrorCodeString.new('cannot be blank', 50)

Now when you return your JSON you can check to see if the error value is an ErrorCodeString and add the error_code value to the output. As ErrorString inherits String, you shouldn't be breaking anything else along the way.

Comments

1

Rails 5 has error.details that can be used for exactly that.

In the model

errors.add(:price, 1023, message: "Transaction value #{price} is above limit (#{maximum_price}).")

In the controller

format.json { render json: @order.errors.details, status: :unprocessable_entity }

error details can be anything, eg. you could also use :above_limit instead of 1023. The API response body will then look like

pp JSON.parse(response)
{"price"=>[{"error"=>1023}]}

This feature has been backported to Rails 4, see also http://blog.bigbinary.com/2016/05/03/rails-5-adds-a-way-to-get-information-about-types-of-failed-validations.html

Also: Is there a way to return error code in addition to error message in rails active record validation?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.