logesh
logesh

Reputation: 2672

How to change the default json response in devise to custom response?

I use devise for authentication and in registration controller if user cannot be created due to some reason then it produces json response as

{"email":["has already been taken"],"password":["doesn't match confirmation"],"username":["has already been taken"]}

but i want this to be changed to the following

{"error":{"email":{"has already been taken"},"password":{"doesn't match confirmation"},"username":{"has already been taken"}}}

How can i do this?

Upvotes: 2

Views: 4152

Answers (4)

Waiting for Dev...
Waiting for Dev...

Reputation: 13037

Extending from @quix answer (I don't leave it as a comment because it has formatting problems).

You can as well minimize overriding just redefining http_auth_body method:

class CustomFailureApp < Devise::FailureApp
  def http_auth_body
    return super unless request_format == :json
    {
      success: false,
      error: i18n_message
    }.to_json
  end
end

Upvotes: 3

qix
qix

Reputation: 7942

For reference in case anyone else stumbles upon this question when looking for how to customize the json error response when a failed login attempt is made using Devise, the key is to use your own custom FailureApp implementation. (You can also use this approach to override some redirect behavior.)

class CustomFailureApp < Devise::FailureApp
  def respond
    if request.format == :json
      json_error_response
    else
      super
    end
  end

  def json_error_response
    self.status = 401
    self.content_type = "application/json"
    self.response_body = [ { message: "Your email or password is incorrect."} ].to_json
  end
end

and in your devise.rb, look for the config.warden section:

  config.warden do |manager|
    manager.failure_app = CustomFailureApp
  end

Some related info:

At first I thought I would have to override Devise::SessionsController, possibly using the recall option passed to warden.authenticate!, but as mentioned here, "recall is not invoked for API requests, only for navigational ones. If you want to customise the http status code, you will have better luck doing so at the failure app level."

Also https://github.com/plataformatec/devise/wiki/How-To%3a-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated

Upvotes: 11

greatghoul
greatghoul

Reputation: 1538

respond do |format|
    format.json { render json: {error: @your_model.errors }}
end

or maybe you should try

respond do |format|
    format.json { render json: {error: Hash[@your_model.errors.map {|k, v| k, v[0]] } }}
end

Upvotes: 0

Antarr Byrd
Antarr Byrd

Reputation: 26131

You should create a json.erb file and render that in that error. This answer shows you how to do that.

Upvotes: 0

Related Questions