设计和处理闪光灯 [英] Devise and handling the flash

查看:128
本文介绍了设计和处理闪光灯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Devise 3.1.1与rails 3,我的布局中有这个Flash处理代码:

  %flash.each do | name,msg | %GT; 
<%= content_tag:section,msg,:id => flash _#{name},:class => flash%>
<%end%>

我登录我的应用程序,Flash说:

 成功登录。 

然后退出登录,然后登录错误,Flash说:

 成功注销。 
电子邮件或密码无效。

我想我明白为什么我收到两条消息,当登录不正确时,没有重定向一个渲染。



不知道如何修复它。

解决方案

我想出了原因。



当您挖掘Devise的SessionsController来源时,您会发现 #create 方法如下:

 #POST / resource / sign_in 
def create
self.resource = warden。 (auth_options)
set_flash_message(:notice,:signed_in)if is_navigational_format?
sign_in(resource_name,resource)
respond_with resource,:location => after_sign_in_path_for(resource)
end

在上面的代码中,Devise设置了闪烁的消息,成功登录这里。这是您看到的消息,因为成功登录。。它使用方法 set_flash_message ,它只是一个 flash [key] =something的包装器。 #destroy 方法也是如此,它显示您成功注销



注意在上面的代码中,有没有代码设置错误信息,如密码或电子邮件无效。那么你看到这个消息呢?它设置在 Devise :: FailureApp

  def recall 
env [PATH_INFO] = attempts_path
flash.now [:alert] = i18n_message(:invalid)
self.response = recall_app(warden_options [:recall])。call(env)
end

请注意,方法是 flash.now ,而不是 flash 。区别是 flash.now 将在当前请求中发送Flash消息,而不是下一个。


默认情况下,将值添加到闪存将使它们可用于下一个请求,但有时您可能希望在同一请求中访问这些值。例如,如果创建操作无法保存资源,并且直接呈现新模板,则不会导致新请求,但您可能仍然希望使用闪存显示消息。要做到这一点,您可以使用flash.now以与使用普通闪光灯相同的方式使用。 http://guides.rubyonrails.org/action_controller_overview.html#the-flash


所以现在揭示了原因。


  1. 您已退出。你碰到 SessionsController#destroy 。 Devise破坏了你的会话,让你再次登录到 / users / sign_in ,渲染'new 模板。 Flash对象包含成功的签出消息,您看到它。


  2. 现在,您尝试在同一页面上登录。这次您的表单提交命中 #create 。如果错误,Devise不会重定向到任何地方,但再次使用 flash.now 再次渲染相同的'new'对象,其中包含登录错误消息。


在步骤2中,最后一个flash对象不会被删除,因为没有新的请求渲染,但添加了另一个新的 flash.now 对象。所以你看到两个消息。



解决方案



当然可以覆盖Devise来改变这种行为,但是这很麻烦,不必要



一个更方便和用户友好的解决方案是,不要登陆用户登录页面无论是登录还是退出



通过设置 store_location 并覆盖 after_sign_in_path_for after_signed_out_path_for 在您的应用程序控制器中。

  def store_location 
disable_pattern = / \ / users /
会话[:previous_url] =请求。 fullpath,除非request.fullpath =〜disable_pattern
end

def after_sign_in_path_for(资源)
会话[:previous_url] || root_path
end

def after_sign_out_path_for(资源)
after_sign_in_path_for(资源)
结束

通过此设置,用户将在登录或注销后登陆他之前浏览过的页面,并且不会在该问题中再次看到两个Flash消息。



原因是当用户退出时,他将重定向到上一页,并看到已签出的消息。当他想要登录时,他需要去登录页面,这是一个新的请求,那么以前的注销闪存将被删除。


I am using Devise 3.1.1 with rails 3 and I have this flash handling code in my layout:

<% flash.each do |name, msg| %>
    <%= content_tag :section, msg, :id => "flash_#{name}", :class => "flash" %>
<% end %>

I sign into my app, flash says:

"Signed in successfully."

then sign out, then sign in incorrectly and flash says:

"Signed out successfully."
"Invalid email or password."

I think I understand why I am getting two messages, when signing in incorrectly there is no redirect, just a render.

Not sure how to fix it though.

解决方案

I figured out the reason.

When you dig into Devise's source of SessionsController, you'll find #create method as follows:

# POST /resource/sign_in
def create
  self.resource = warden.authenticate!(auth_options)
  set_flash_message(:notice, :signed_in) if is_navigational_format?
  sign_in(resource_name, resource)
  respond_with resource, :location => after_sign_in_path_for(resource)
end

In above code, Devise sets flash message for success signed in here. That's what the message you saw as "Signed in successfully.". It uses the method set_flash_message which is just a wrapper of flash[key]= "something". The same is true for #destroy method which show you "Signed out successfully".

Note in above code, there is no code to set error message such as "Invalid password or email". So how comes this message you saw? It is set in Devise::FailureApp

def recall
  env["PATH_INFO"]  = attempted_path
  flash.now[:alert] = i18n_message(:invalid)
  self.response = recall_app(warden_options[:recall]).call(env)
end

Note here, the method is flash.now, not flash. The difference is flash.now will deliver flash message in current request, not next.

By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the create action fails to save a resource and you render the new template directly, that's not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use flash.now in the same way you use the normal flash. http://guides.rubyonrails.org/action_controller_overview.html#the-flash

So the reason is revealed now.

  1. You signed out. You hit SessionsController#destroy. Devise destroyed your session, brings you to /users/sign_in, render 'new template for your sign in again. The flash object contains the successful signed out message and you saw it.

  2. Now you tried to sign in in same page. This time your form submit hit #create. If error, Devise will not redirect you to anywhere but render the same 'new' template again with the flash.now object which contains sign in error message.

In step 2, you last flash object is not removed because no new request rendered, but another new flash.now object is added. So you see two message.

Solution

Of course it's possible to override Devise to change this behaviour, but that's troublesome and unnecessary.

A more convenient and user-friendly solution is, do not land the user on sign in page after either signed in or signed out.

This is easily by setting store_location and override after_sign_in_path_for and after_signed_out_path_for in your application controller.

def store_location
  disable_pattern = /\/users/
  session[:previous_url] = request.fullpath unless request.fullpath =~ disable_pattern
end

def after_sign_in_path_for(resource)
  session[:previous_url] || root_path
end

def after_sign_out_path_for(resource)
  after_sign_in_path_for(resource)
end

By this setting the user will land on his previously browsed page either after signed in or signed out, and they will not see two flash messages in the question again.

The reason is, when the user signed out, he will be redirect to previous page and see the signed out message. When he want to sign in, he need to go to sign in page which is a new request, then the previous signed out flash will be removed.

这篇关于设计和处理闪光灯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆