5

In a controller, I want to replace if..render..else..render with respond_with:

# Current implementation (unwanted)
def create
  @product = Product.create(product_params)
  if @product.errors.empty?
    render json: @product
  else
    render json: { message: @product.errors.full_messages.to_sentence }
  end
end

# Desired implementation (wanted!)
def create
  @product = Product.create(product_params)
  respond_with(@product)
end

The problem with respond_with is that, in case of a validation error, the JSON renders in a specific way that doesn't fit what the client application expects:

# What the client application expects:
{
  "message": "Price must be greater than 0 and name can't be blank"
}

# What respond_with delivers (unwanted):
{
  "errors": {
    "price": [
      "must be greater than 0"
    ],
    "name": [
      "can't be blank"
    ]
  }
}

Product, price and name are examples. I want this behavior through the entire application.

I am using the responders gem and I've read it's possible to customize responders and serializers. But how do the pieces fit together?

How to customize the JSON that respond_with renders in case of validation errors?

João Souza
  • 4,032
  • 3
  • 25
  • 38

2 Answers2

3

A couple other ways to customize user alerts

You can just put it in line:

render json: { message: "Price must be greater than 0" }

or: You can just reference your [locale file] and put in custom messages there. 1:

t(:message)

Hope this helps :)

gwalshington
  • 1,418
  • 2
  • 30
  • 60
  • Thanks for the answer. This is my current implementation, actually. But what I really want is to use responders like `respond_with(@product)` and customize the error layout for error responses. – João Souza Jun 12 '17 at 17:50
  • Have you tried putting in a variable? Is the issue that the word "Price" is not coming up in the error message? – gwalshington Jun 12 '17 at 18:34
  • The issue is not the word "Price" not coming. The issue is that I'm expected to use `respond_with` in the controller (not `render json:`) and, in case of validation errors, render a JSON that contains the `message` node with all full error messages concatenated as a sentence -- again, while using `respond_with` in the controller, not `render json:`. – João Souza Jun 13 '17 at 13:23
0

I found a provisory way to get the errors hash as a single sentence. But not only is it hackish, but it also does not match the desired output 100%. I still hope there is a way to do this with a custom serializer or responder.

module ActiveModel
  class Errors
    def as_json(*args)
      full_messages.to_sentence
    end
  end
end

# OUTPUT
{
  "errors": "Price must be greater than 0 and name can't be blank"
}
João Souza
  • 4,032
  • 3
  • 25
  • 38