Reputation: 167
I am working on an app which needs has both website and an api and I am implementing a common Devise authentication for that. To implement this requirement I am overriding Devise Registrations Controller to respond to both html and json. For json I want the controller to return the user data and I am able to implement this, but for html I want to use the original devise behavior of signing in and redirecting to root path.
The code for Registrations Controller is:
class RegistrationsController < Devise::RegistrationsController
def create
@user = User.create(user_params)
respond_to do |format|
format.html {
@user.save ? (super) : (render :new)
}
format.json {
@user.save ? (render :json => {:state => {:code => 0}, :data => @user }) :
(render :json => {:state => {:code => 1, :messages => @user.errors.full_messages} })
}
end
end
private
def user_params
params.require(:user).permit(:email, :password)
end
end
Using this controller I get a validation error Email has already been taken but when I check my logs it shows the user has been created.
Can anyone tell me what error I am doing? I just want my controller to fallback to original devise functionality in case of html request.
Upvotes: 1
Views: 2544
Reputation: 34338
Here is the working version of the code (tested locally myself). You controller should look like:
def create
@user = User.create(user_params)
respond_to do |format|
format.html {
@user.save ? (render @user) : (render 'layouts/application')
}
format.json {
@user.save ? (render :json => {:state => {:code => 0}, :data => @user }) :
(render :json => {:state => {:code => 1, :messages => @user.errors.full_messages} })
}
end
end
Add a _user
partial app/views/users/_user.html.erb
:
<p>
<%= @user.email %>
<%= @user.created_at %>
<%= @user.updated_at %>
</p>
So, the changes are minimal. Once you make these changes, your RegistrationsController#create
action will work successfully for HTML format.
Upvotes: 0
Reputation: 7327
The problem was when you used HTML, you created the user twice by running both @user = User.create(user_params)
and super
. I moved that first line of code to JSON format, and HTML to only run super
.
class RegistrationsController < Devise::RegistrationsController
def create
respond_to do |format|
format.html {
super
}
format.json {
@user = User.create(user_params)
@user.save ? (render :json => {:state => {:code => 0}, :data => @user }) :
(render :json => {:state => {:code => 1, :messages => @user.errors.full_messages} })
}
end
end
private
def user_params
params.require(:user).permit(:email, :password)
end
end
Upvotes: 2