I'm developing an app with Ruby on Rails and bootstrap. I'm using the Devise gem for the authentication system. I generated the devise views but I don't like to use the pages/views for sign in/sign up. Instead I got a popup modal/form which I'm using. Right now my Sign In form looks like this:
<div class="form loginBox">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.email_field :email, :class => "form-control", :placeholder => "Email" %>
<%= f.password_field :password, :class => "form-control", :placeholder => "Password", autocomplete: "off" %>
<% if devise_mapping.rememberable? -%>
<%= f.check_box :remember_me, :style => "margin-top:20px;margin-bottom:20px;" %>
<%= f.label :remember_me, :style => "margin-top:20px;margin-bottom:20px;" %>
<% end -%>
<%= f.submit "Sign In", :class => "btn btn-default btn-login" %>
<% end %>
</div>
I put this in the application helper:
module ApplicationHelper
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
end
When I press the Sign In button (submit-button) without filling out the fields I'm redirected to the /users/sign_in page where I get the devise error messages. The same happens with my registration form.
How can I prevent this from happening? What should I do about the original devise views to not show them? Am I doing this the wrong way?
I'm quite new with Ruby and Rails and I'm happy I atleast got the authentication Sign In/Sign Up process to work using the popup forms I have. Its just that I'm not sure I did this the right way as I got the problem mentioned above.
Thanks a lot in advance! /Jacob
You need a custom sessions controller and some extra configuration.
Step 1: Enable devise to respond with JSON
# config/initializers/devise.rb
config.http_authenticatable_on_xhr = false
config.navigational_formats = ["*/*", :html, :json]
Step 2: Add mappings (I can see that you already did that)
# app/helpers/application_helper.rb
module ApplicationHelper
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
end
Step 3: Add a custom controller
# app/controllers/sessions_controller.rb
class SessionsController
def create
resource = warden.authenticate!(:scope => resource_name, :recall => '#{controller_path}#failure')
sign_in_and_redirect(resource_name, resource)
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true}
end
def failure
return render :json => {:success => false, :errors => ["Login failed."]}
end
end
Here what's special about the controller is that we return everything in :json
Step 3: Override the controllers:
# config/routes.rb
devise_for :users, :controllers => {sessions: 'sessions'}
Now devise uses the custom sessions controller.
Step 4: Add your custom form (with :remote=> true)
%h2 Sign in
<%= devise_error_messages! %>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name) ,:html => {:id => "login-box"},:format => :json, :remote => true ) do |f| %>
<%= f.password_field :password, :class => "form-control", :placeholder => "Password", autocomplete: "off" %>
<% if devise_mapping.rememberable? -%>
<%= f.check_box :remember_me, :style => "margin-top:20px;margin-bottom:20px;" %>
<%= f.label :remember_me, :style => "margin-top:20px;margin-bottom:20px;" %>
<% end -%>
<%= f.submit "Sign In", :class => "btn btn-default btn-login" %>
<% end %>
</div>
Step 5: Add the javascript
$("form#login-box").bind "ajax:success", (e, data, status, xhr) ->
if data.success
//javascript that executes if everything goes o.k.
$('#sign_in').modal('hide')
$('#sign_in_button').hide()
$('#submit_comment').slideToggle(1000, "easeOutBack" )
else
alert('failure!')
This should work
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.