设计Ajax登录:’sessions#create’仅在成功时渲染’create.js.erb’

我的目标是使用Devise实现Ajax登录解决方案,并尽可能减少模式的变化。 我已经部分地达到了它,但是故障回调存在一个问题。 让我解释一下这个场景:

  1. 使用remote: true显示模式中的登录表单remote: true Rails / UJS约定(OK);
  2. 创建自定义sessions控制器并指向Devise(OK);
  3. 创建一个JS视图文件create.js.erb来响应sessions#create create.js.erb action(问题);

问题:我的create.js.erb只包含一个alert("Test ok") 。 当我使用正确的凭据提交sessions#new create.js.erb ,执行文件create.js.erb ,将显示alert 。 但如果凭证错误,则返回401 Unauthorized status并忽略create.js.erb

也许有人知道在登录失败时使create.js.erb运行的快速技巧。 这样我就不需要创建独立的Ajax脚本或更改整个sessions控制器。

谢谢,

环境:

 VERSIONS: Rails 4.0.2 Devise 3.2.2 

定制会话控制器:

 class Website::SessionsController < ::Devise::SessionsController respond_to :js # without it neither on success create.js.erb runs layout false # action `new` pure html which is rendered in a modal box end 

会议/ create.js.erb

 alert("Test ok"); 

登录失败时的服务器日志:

 Started POST "/users/sign_in" for 127.0.0.1 at 2014-03-27 09:59:47 -0300 Processing by Website::SessionsController#create as JS Parameters: {"utf8"=>"✓", "user"=>{"email"=>"", "password"=>"[FILTERED]"}, "commit"=>"Fazer login"} Completed 401 Unauthorized in 1ms 

出现问题的原因是:

warden.authenticate!(…)

它会引发exception并且不会在之后呈现您的视图。

您应该为自己的行为覆盖SessionsController #create动作。 例如这样:

 def create self.resource = warden.authenticate(auth_options) if resource && resource.active_for_authentication? ... sign_in(resource_name, resource) ... else ... end end 

成功后,将呈现create.js.erb模板。

如果由于任何原因失败,则会呈现new.js.erb模板。

处理此问题的最简单方法是简单地添加new.js.erb 。 这涉及对设计控制器的最少量修改。


值得注意的是,除了向表单添加remote: true之外,我还必须进行以下调整,甚至可以获取create.js.erb进行渲染。

config / initializers / devise

 # If http headers should be returned for AJAX requests. True by default. config.http_authenticatable_on_xhr = false 

config / routes.rb

 devise_for :users, controllers: { sessions: 'users/sessions' } 

controllers / users / sessions_controller.rb

 class Users::SessionsController < Devise::SessionsController respond_to :html, :js end