我已经通过几个指南介绍了如何实现ajax授权,但没有使用Rails 5.0.0在我的环境中工作
所以,我有:
Users::SessionsController < Devise::SessionsController
def create
resource = User.find_for_database_authentication(email: params[:user][:email])
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user][:password])
sign_in :user, resource
return render nothing: true
end
invalid_login_attempt
end
protected
def invalid_login_attempt
set_flash_message(:alert, :invalid)
render json: flash[:alert], status: 401
end
devise_for :users, :controllers => {sessions: 'users/sessions', registrations: 'users/registrations'}, :path_names => { :sign_in => 'login' }
<%= form_for(resource, url: session_path(:user), :html => {:id => "login-box", :class => "contact-form"}, :remote => true ) do |f| %>
$(document).ready(function() {
//form id
$('#login-box').ajaxSuccess( function(evt, data, status, xhr) {
console.log('success');
});
$('#login-box').ajaxFail(function(evt, xhr, status, error) {
console.log(xhr.responseText);
});
});
config.http_authenticatable_on_xhr = false
config.navigational_formats = ["*/*", :html, :json]
当我尝试登录时,我收到无效数据的响应
Started POST "/users/login" for 127.0.0.1 at 2016-10-20 18:29:55 +0300
Processing by Users::SessionsController#create as JS
Parameters: {"utf8"=>"✓", "user"=>{"email"=>"", "password"=>"[FILTERED]", "remember_me"=>"0"}, "button"=>""}
User Load (1.5ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["email", ""], ["LIMIT", 1]]
Completed 401 Unauthorized in 4ms (Views: 0.3ms | ActiveRecord: 1.5ms)
这个有效(它确认,但是ajax没有触发,必须手动重新加载页面以检查我是否已登录)
Started POST "/users/login" for 127.0.0.1 at 2016-10-20 18:31:29 +0300
Processing by Users::SessionsController#create as JS
Parameters: {"utf8"=>"✓", "user"=>{"email"=>"xs290@me.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "button"=>""}
......
(3.4ms) COMMIT
(0.1ms) BEGIN
....
(0.4ms) COMMIT
Rendering text template
Rendered text template (0.0ms)
Completed 200 OK in 176ms (Views: 3.7ms | ActiveRecord: 7.0ms)
答案 0 :(得分:1)
I was actually surprised at how easy it was once you drop all that Rails UJS "ajax for idiots" nonsense.
Setup a basic form. This is based on the devise/sessions/new
view.
# remote: false is not really needed.
<%= form_for(User.new, as: :user, url: session_path(:user), html: { id: 'login-form'}, remote: false ) do |f| %>
<div class="errors"></div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
And the just your run of the mill ajax handler:
$(document).on('submit', '#login-form', function(){
var $form, $btn;
$form = $(this);
$btn = $form.find('input[type="submit"]');
$form.find('.errors').remove();
$.post({
url: this.action,
data: $form.serialize()
}).error(function(jqXHR, textStatus, errorThrown){
$form.prepend('<div class="errors">Invalid email or password</div>');
// Unlocks the UI button
$btn.prop( "disabled", false );
});
// prevent default submission
return false;
});
If you are using turbolinks it will automatically pick up the ajax success event and clear the page cache and reload the page.
Otherwise just add a .done
callback to the promise.
$.post({
url: this.action,
data: $form.serialize()
}).error(function(jqXHR, textStatus, errorThrown){
$form.prepend('<div class="errors">Invalid email or password</div>');
// Unlocks the UI button
$btn.prop( "disabled", false );
}).done(function(data, textStatus, jqXHR){
window.location.reload();
});
答案 1 :(得分:1)
好吧,在网上阅读了更多关于这个问题之后,我开发了基于this article的解决方案(不是英文版,但我相信提及来源是公平的)。
我想我的问题主要是解雇ajax事件。
会话/新视图
<%= form_for(User.new, url: session_path(:user), :html => {:id => "login-box", :class => "contact-form", :'data-type' => 'json'}, :remote => true ) do |f| %>
设计配置(返回默认值)
config.http_authenticatable_on_xhr = true
会话控制器
class Users::SessionsController < Devise::SessionsController
respond_to :html, :json
end
这是正确的,没有额外的代码给控制器。这对html和ajax请求都适用。如果您有一些必需的current_user并且您有redirect_to:login_path(例如创建新帖子),那么它会非常有用
最后也是最重要的一点 的 jquery的强> 代码对我来说非常适合
$(document).on('ajax:success', '#login-box', function(e) {
return $.magnificPopup.close();
window.location.reload();
});
$(document).on('ajax:error', '#login-box', function(event, xhr, settings, exceptions) {
var error_messages;
error_messages = xhr.responseJSON['error'] ? "<div class='alert alert-danger pull-left'>" + xhr.responseJSON['error'] + "</div>" : xhr.responseJSON['errors'] ? $.map(xhr.responseJSON["errors"], function(v, k) {
return "<div class='alert alert-danger pull-left'>" + k + " " + v + "</div>";
}).join("") : "<div class='alert alert-danger pull-left'>Unknown error</div>";
return $('#login-box').prepend(error_messages);
});