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

Edi*_*ado 4 ruby-on-rails devise

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

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

问题:我create.js.erb只包含一个alert("Test ok").当我sessions#new使用正确的凭据提交表单时create.js.erb,将alert显示该文件.但是如果凭证不正确,则返回401 Unauthorized状态并被create.js.erb忽略.

create.js.erb当登录失败时,也许有人知道快速操作.这样我就不需要创建独立的Ajax脚本或更改整个sessions控制器.

谢谢,

环境:

VERSIONS:
Rails 4.0.2
Devise 3.2.2
Run Code Online (Sandbox Code Playgroud)

定制会话控制器:

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
Run Code Online (Sandbox Code Playgroud)

会议/ create.js.erb

alert("Test ok");
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

Bra*_*rth 8

成功后,将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
Run Code Online (Sandbox Code Playgroud)

config/routes.rb:

devise_for :users, controllers: { sessions: 'users/sessions' }
Run Code Online (Sandbox Code Playgroud)

controllers/users/sessions_controller.rb:

class Users::SessionsController < Devise::SessionsController

  respond_to :html, :js

end
Run Code Online (Sandbox Code Playgroud)

  • 我使用相同的逻辑,但没有为 js 请求设置 Flash 消息。有什么猜测吗? (2认同)

And*_*rey 4

出现问题的原因是:

典狱长.验证!(...)

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

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

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