设计Ajax登录:’sessions#create’仅在成功时渲染’create.js.erb’
我的目标是使用Devise实现Ajax登录解决方案,并尽可能减少模式的变化。 我已经部分地达到了它,但是故障回调存在一个问题。 让我解释一下这个场景:
- 使用
remote: true
显示模式中的登录表单remote: true
Rails / UJS约定(OK); - 创建自定义
sessions
控制器并指向Devise(OK); - 创建一个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