/ Authentication / Simplest Ajax login and signup with better error handling (Rails & Devise)

SESSION CONTROLLER

class SessionsController < Devise::SessionsController  
    respond_to :json
end

 

REGISTRATION CONTROLLER

class RegistrationsController < Devise::RegistrationsController

  respond_to :json

  def create
    super
  end

  def update

    # For Rails 4
    account_update_params = devise_parameter_sanitizer.sanitize(:account_update)

    # required for settings form to submit when password is left blank
    if account_update_params[:password].blank?
      account_update_params.delete("password")
      account_update_params.delete("password_confirmation")
    end

    @user = User.find(current_user.id)
    
    # Get the form id, so we could clear the fields after remote update
    # Also use to differentiate function to be used during update
    @form_id = params[:user][:form_id]

    @update = nil
    if @form_id == "update-password-form"
      @update = update_resource(@user, account_update_params)
    else    
      @update = @user.update_attributes(account_update_params)
    end

    if @update       
      # Sign in the user bypassing validation in case their password changed
      sign_in @user, :bypass => true
    end

    respond_to do |format|
      format.html
      format.js
    end
  end
  
end

 

LOGIN VIEW

<div class="row row-centered">
  <div class="col-md-5 col-centered">
    <div class="panel signup-login-form-container col-min col-max">

      <div id="js-error-block" class="alert alert-danger" style="display:none;">
        <i class="fa fa-exclamation-circle" aria-hidden="true"></i> Invalid email or password.
      </div>

      <%= form_for(resource, as: resource_name, url: session_path(resource_name), :html => { :id => "ajax_signin"}) do |f| %>
        <div class="field form-group">
          <%= f.email_field :email, autofocus: true, class: "form-control decorative-input inspectletIgnore", placeholder: "Email address", required: "required" %>
        </div>

        <div class="field form-group">
          <%= f.password_field :password, autocomplete: "off", class: "form-control decorative-input inspectletIgnore", placeholder: "Password", required: "required" %>
        </div>

        <div class="clearfix">
          <%= f.check_box :remember_me, class: "remember_me" %> Remember me
            
          <%= link_to "Forgot password?", new_password_path(resource_name), class: "forgot-password pull-right" %>
        </div>

        <div class="actions">
          <%= f.submit "Log in", class: "btn btn-primary btn-block signup-login-form__btn-xl btn-large" %>
        </div>

        <ul class="omniauth-links">
          <li><%= link_to "Log in with Twitter", user_omniauth_authorize_path(:twitter) %></li>
          <li><%= link_to "Log in with Facebook", user_omniauth_authorize_path(:facebook) %></li>
          <li><%= link_to "Log in with Linkedin", user_omniauth_authorize_path(:linkedin) %></li>
          <li><%= link_to "Log in with Github", user_omniauth_authorize_path(:github) %></li>
          <li><%= link_to "Log in with Google", user_omniauth_authorize_path(:google_oauth2) %></li>
        </ul>

      <% end %>

      <div class="panel-footer panel-footer-authenthicate">
        <div class="clearfix">
          <span class="signup-login-form__switch-copy">
            Don't have an account?
          </span>
          <%= link_to "Sign up", new_user_registration_path, class: "btn btn-default pull-right signup-login-form__btn-rausch-border" %>              
        </div>
      </div>

    </div>
  </div>
</div>

 

REGISTRATION VIEW

 

<div class="row row-centered">
<div class="col-md-5 col-centered">
<div class="panel signup-login-form-container col-min col-max">

<div id="js-error-block" class="alert alert-danger" style="display:none;">
<ul></ul>
</div>

<% if !params[:callback].blank? && params[:callback] == "twitter" %>
<h2>Almost there :)</h2>

<p>Finish creating your account by entering your email address.</p>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>

<div class="field">
<%= f.email_field :email, autofocus: true, class: "form-control decorative-input inspectletIgnore", placeholder: "Email address", required: "required" %>
</div>

<div class="actions">
<%= f.submit "Create account", class: "btn btn-primary btn-block signup-login-form__btn-xl btn-large" %>
</div>
<% end %>

<br/>

<% else %>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), :html => { :id => "ajax_signup"}) do |f| %>

<div class="field form-group">
<%= f.text_field :first_name, class: "form-control decorative-input", placeholder: "First name", required: "required" %>
</div>

<div class="field form-group">
<%= f.text_field :last_name, class: "form-control decorative-input", placeholder: "Last name", required: "required" %>
</div>

<div class="field form-group">
<%= f.email_field :email, autofocus: true, class: "form-control decorative-input inspectletIgnore", placeholder: "Email address", required: "required" %>
</div>

<div class="field form-group">
<%= f.password_field :password, autocomplete: "off", class: "form-control decorative-input inspectletIgnore", placeholder: "Password", required: "required" %>
</div>

<div class="actions">
<%= f.submit "Sign up", class: "btn btn-primary btn-block signup-login-form__btn-xl btn-large" %>
</div>

<% end %>

<ul class="omniauth-links">
<li><%= link_to "Sign up with Twitter", user_omniauth_authorize_path(:twitter) %></li>
<li><%= link_to "Sign up with Facebook", user_omniauth_authorize_path(:facebook) %></li>
<li><%= link_to "Sign up with Linkedin", user_omniauth_authorize_path(:linkedin) %></li>
<li><%= link_to "Sign up with Github", user_omniauth_authorize_path(:github) %></li>
<li><%= link_to "Sign up with Google", user_omniauth_authorize_path(:google_oauth2) %></li>
</ul>

<% end %>

<div class="panel-footer panel-footer-authenthicate">
<div class="clearfix">
<span class="signup-login-form__switch-copy">
Already a member?
</span>
<%= link_to "Log in", new_user_session_path, class: "btn btn-default pull-right signup-login-form__btn-rausch-border" %> 
</div>
</div>

</div>
</div>
</div>

 JAVASCRIPT

 

$(document).ready(function(){

  $.fn.serializeObject = function() {
    var values = {}
    $("form input, form select, form textarea").each( function(){
      values[this.name] = $(this).val();
    });
    
    return values;
  }

  function clear_errors() {
    $('#js-error-block ul').html('');
    $('.form-control').attr('style','1px solid #ccc;');
  }

  String.prototype.titleize = function() {
    return this.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
  };

  $("form#ajax_signin").submit(function(e){
     e.preventDefault(); 
     var user_info = $(this).serializeObject();
     $.ajax({
       type: "POST",
       url: "http://localhost:3000/users/sign_in",
       data: user_info,
       success: function(json){
          location.href = "/";;
       },
       error: function(xhr) { 
          /** ACTIVATE THIS IF YOU GOT MORE THAN EMAIL OR PASSWORD FIELDS
          var errors = jQuery.parseJSON(xhr.responseText).errors; 
          for (messages in errors) { 
            error_messages =  messages + ' ' + errors[messages];
          } 
          */

          $('#js-error-block-login').show();
       }, 
       dataType: "json"
     });
  });
  
  $("form#ajax_signup").submit(function(e){
     e.preventDefault(); 
     var user_info = $(this).serializeObject();
     $.ajax({
       type: "POST",
       url: "http://localhost:3000/users",
       data: user_info,
       success: function(json){
          location.href = "/";;
       },
       error: function(xhr) { 
         	
         	var errors = jQuery.parseJSON(xhr.responseText).errors; 
         	for (messages in errors) { 
         		error_messages =  messages.titleize() + ' ' + errors[messages];
            var field = "form#ajax_signup " + "#user_" + messages;
            var error_message = error_messages;

            console.log(error_messages);

            //alert(error_messages);

            $('#js-error-block-signup ul').append("<li>"+error_messages+"</li>");
            $(field).css('border', '1px solid #D9534F');          
         	} 

          $('#js-error-block-signup').show();
       }, 
       dataType: "json"
     });

     clear_errors();
  });

});

 

 

 

No video for this post.

No issues for this post.

by ryzalyusoff