How To Hack Devise and Sign Up Your Users via Ajax In Rails

Let’s say you want your users to sign up in order to leave a comment or do whatever other actions you want in your application. Well, it’s not a great experience if the user clicks on “Leave a Comment”, then gets redirected to the sign up page, then gets redirected back. What if, instead, you can get a nice sign up modal to pop up. The user signs up, the modal is hidden, and the user can leave a comment!

Well, this is exactly the functionality I was working on in my app, so I wanted to share how you can do it too.

Generate Devise Views

First, in case you’re not familiar with it, devise is an incredible rails gem that handles all user authentication stuff. Once you got the basic devise functionality setup by following the README, make sure to generate the devise views inside your own app as well. The wiki page explains it all, so I won’t go into detail on this part of the process.

Configure Devise To Accept JSON

First, we need to configure devise to accept a JSON request, which is what our AJAX will send it. To do that, simply change the following variables in your config/initializers/devise.rb file:

# config/initializers/devise.rb

config.http_authenticatable_on_xhr = false
config.navigational_formats = ["*/*", :html, :json]

Create A Registrations Controller

The sign up action happens from the devise registrations controller. You’ll have to overwrite the controller to respond with JSON. So just create a registrations controller, and here is an example of how you would overwrite it:

# app/controllers/registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController

  def create

      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_navigational_format?
        sign_up(resource_name, resource)
        return render :json => {:success => true}
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
        return render :json => {:success => true}
      clean_up_passwords resource
      return render :json => {:success => false}

  # Signs in a user on sign up. You can overwrite this method in your own
  # RegistrationsController.
  def sign_up(resource_name, resource)
    sign_in(resource_name, resource)


Keep in mind that you now have control over the json that will be returned, so you can customize it to whatever you think it should be, especially for when the sign up is unsuccessful due to validation errors.

Add Devise Mappings To Your Application Helper

Since devise is using the generic “resource” in it’s code, you need to map your user model to the devise resource. You can do that by adding the following to your applications helper or the helper file for the controller where you’d like to use the devise ajax functionality:

# app/helpers/application_helper.rb

module ApplicationsHelper
  def resource_name

  def resource
    @resource ||=

  def devise_mapping
    @devise_mapping ||= Devise.mappings[:user]

Redirect Routes!

In case you’ve tried the above steps and nothing changed, that’s because you have to redirect devise to use your controller instead of it’s own. This is done very easily in your routes file:

# config/routes.rb
  devise_for :users, :controllers => {registrations: 'registrations'}

Update Your Sign Up Form

This is where those devise views in your rails app become handy. The form_for helper accepts a :remote => true¬†options, which automatically posts the form remotely (via ajax) for you, and the :format => :json option converts your form information into json. Here is what your form should look like (if you’re using haml):

- # app/views/devise/registrations/new.html.haml

%h2 Sign up
= form_for(resource, :as => resource_name,
           :url => registration_path(resource_name),
           :html => {:id => "sign_up_user"},
           :format => :json,
           :remote => true ) do |f|
  = devise_error_messages!
    = f.text_field :username, placeholder: "name"
    = f.email_field :email, placeholder: 'email'
    = f.password_field :password, placeholder: "password"
    = f.password_field :password_confirmation, placeholder: "password confirmation"
  %div= f.submit "Sign up", class: 'btn btn-success btn-medium'

Add The JavaScripts

And, of course, you need JavaScript to catch the ajax response from your server and handle it on the client side. Here is an example (in coffeescript):

# app/assets/javascripts/

$("form#sign_up_user").bind "ajax:success", (e, data, status, xhr) ->
    if data.success
      $('#submit_comment').slideToggle(1000, "easeOutBack" )

And now, everything should be working! Magic, right?!

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.