Reputation: 2672
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
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
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."
Upvotes: 11
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
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