设计和处理闪光灯

2024-04-25

我正在将 Devise 3.1.1 与 Rails 3 一起使用,并且我的布局中有以下闪存处理代码:

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

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

"Signed in successfully."

然后注销,然后错误登录并闪烁显示:

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

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

但不知道如何解决它。


我明白了原因。

当你深入研究 Devise 的 SessionsController 源码时,你会发现#create方法如下:

# 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

在上面的代码中,Devise 设置了此处登录成功的闪现消息。这就是您看到的消息"Signed in successfully."。它使用的方法set_flash_message这只是一个包装flash[key]= "something"。对于#destroy向您展示的方法"Signed out successfully".

注意上面的代码中有没有代码来设置错误消息例如“密码或电子邮件无效”。那么你是怎么看到这条消息的呢?它设置在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

这里注意一下,方法是flash.now, not flash。区别在于flash.now将在当前请求中传递 Flash 消息,而不是下一个请求。

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

那么原因现在就揭晓了。

  1. 你退出了。你击中了SessionsController#destroy。设计破坏了你的会话,让你/users/sign_in, 使成为'new供您再次登录的模板。 Flash 对象包含成功注销的消息,您可以看到它。

  2. 现在您尝试在同一页面登录。这次你的表单提交成功了#create。如果出现错误,Devise 不会将您重定向到任何地方,而是呈现相同的内容'new'再次使用模板flash.now包含登录错误消息的对象。

在步骤 2 中,最后一个 Flash 对象不会被删除,因为没有呈现新的请求,而是另一个新的请求flash.now对象已添加。所以你会看到两条消息。

Solution

当然可以重写 Devise 来改变这种行为,但这很麻烦而且不必要.

更方便和用户友好的解决方案是,登录或注销后不要让用户进入登录页面.

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

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

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

原因是,当用户注销时,他将被重定向到上一页并看到注销消息。当他想要登录时,他需要进入登录页面,这是一个新的请求,那么之前登录的Flash将被删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计和处理闪光灯 的相关文章

随机推荐

  • 如何在 SQL Server 中生成并手动插入唯一标识符?

    我正在尝试在表中手动创建一个新用户 但发现如果代码不抛出异常 就不可能生成 UniqueIdentifier 类型 这是我的例子 DECLARE id uniqueidentifier SET id NEWID INSERT INTO db
  • vue/vuetify 模态模式或最佳实践设计

    在我正在开发的应用程序中 我们有很多模态 每个模态包含少量数据 通常是 2 3 个字段 有时是复选框 列表等 问题是当组件关闭时如何从内部重置 销毁组件 造成这种情况的原因有两个 1 不必清除每个模式上的各个数据字段 2 当第二次打开模式时
  • Eclipse(在 Ubuntu 上)没有 jsp、html 和其他 Web 文件模板

    我使用 Synaptic Package Manager Ubuntu 9 10 安装了 Eclipse 但是 我的 Eclipse 没有任何 HTML 模板 在 新建 对话框中 或 JSP 模板 我该如何修复它 以便我在那里拥有一些 HT
  • Python根据for循环索引创建变量[重复]

    这个问题在这里已经有答案了 我正在尝试为 for 循环的每次迭代创建变量 对于范围 10 内的 i x i abc 这样我就可以得到 x1 x2 x3 x4 x10 都等于 abc 有人知道该怎么做吗 谢谢 你不应该这样做 将你的值存储在d
  • 使用 Base64 和 JSON 上传大图像

    我正在使用此功能将图像上传到服务器JSON 为此 我首先将图像转换为NSData然后到NSString using Base64 当图像不是很大时 该方法工作正常 但当我尝试上传 2Mb 图像时 它会崩溃 问题是服务器没有收到我的图像 即使
  • 使用 Appcompat v7 的抽屉式导航 - ?android:attr 标签的问题

    我在我的项目中使用操作栏和导航抽屉 使用 appcompat v7 和 v4 我已经添加了 appcompat v7 和资源 以下是我的导航抽屉列表的文本视图 直接取自位于以下位置的 Android 示例应用程序 创建抽屉式导航 http
  • C#:通过反射检索和使用 IntPtr*

    我目前正在编写一些代码 这些代码反映了从调用本机 dll 中编组回来的结构 某些结构包含指向以 null 结尾的指针数组的 IntPtr 字段 这些领域需要特殊处理 当反映结构时 我可以识别这些字段 因为它们是由自定义属性标记的 以下说明了
  • ant-找不到符号@Test

    我正在尝试编译以下仅包含一个函数的类 公共类测试注释 Test public void testLogin System out println Testing Login 当我将文件作为 JUNIt 运行时 它可以工作 但是当我尝试从 b
  • 计算 a*a mod n 且不溢出

    I need to calculate a a mod n but a is fairly large resulting in overflow when I square it Doing a n a n n doesn t work
  • 树莓派蓝牙4.0连接

    我正在尝试使用 CoreBluetooth 蓝牙 4 0 通过 iPhone 连接到 Raspberry Pi 我已经发现了该设备并使用以下代码发出连接请求 if peripheral self foundPeripheral NSLog
  • Javascript ResizeObserver 意外触发

    Why the ResizeObserver类总是首先执行处理程序observe 尝试在 Chrome 开发工具上执行以下代码 new ResizeObserver gt console log resize detected observ
  • 从 asp.net 中的 dataSet 获取单个值

    我正在执行查询以从 tbl message 表获取 Title 和 RespondBY 我想在对转发器进行数据绑定之前解密标题 在进行数据绑定之前如何访问标题值 string MysqlStatement SELECT Title Resp
  • jQuery 显示/隐藏/切换有效,但没有保持应有的状态 - 它恢复到原始状态

    我尝试使用 jQuery 显示 隐藏常见问题解答 这个想法是列出所有问题 只有当用户想要查看答案时 他们才会单击问题 看起来像链接 然后答案就会变得可见 它有点有效 只不过一旦单击答案就会恢复到其原始状态 在这种情况下 这意味着当我单击问题
  • 对一列进行唯一约束,排除其他列中具有相同值的行

    我想向列添加唯一键value但我必须忽略列中具有相同值的行value and header id 例如 考虑这个表 id header id value 1 1 a 2 1 a 3 2 a 因此 第 1 行和第 2 行指向同一个对象 并且唯
  • 您可以在不同的 OSGi 包中拥有 JSF 自定义组件吗?

    有人同时使用过 OSGi 和 JSF 吗 我问这个问题是因为 JSF 使用类加载器魔法来查找自定义组件 来自教程 重点是我的 这个配置文件最终会 是 META INF faces config xml 中 代表此的 jar 文件 成分 JS
  • 如何在没有 Intent 的情况下以编程方式拨打电话

    我是 Android 新手 我想在不使用intent 我知道这段代码 Intent intent new Intent Intent ACTION CALL intent setData Uri parse tel bundle getSt
  • 如何将焦点设置到重复控件内的编辑框?

    我想将焦点设置为 将光标置于重复控件中的编辑框 最后一个 重复位于面板 panelRep 内 然后我在面板外面有一个按钮 这是几乎可以工作的按钮的客户端代码 焦点已设置 字段周围的蓝色边框 但光标未放置在字段中 用户仍必须单击该字段才能写入
  • C++ 中可重用的成员函数

    我正在使用这个成员函数来获取指向对象的指针 virtual Object Create return new Object 它是虚拟的 所以我可以获得指向派生对象的指针 现在我这样做 virtual Object Create return
  • 如何在 Google Cloud Platform (GCP) 中测试 Cloud Function?

    我一直在试图寻找这个问题的答案 但无法在任何地方找到它 在 Google Cloud Platform 控制台的 Cloud Functions 部分上 有一个部分标题为 测试 但我不知道应该在此处放置什么来测试该函数 即语法 I have
  • 设计和处理闪光灯

    我正在将 Devise 3 1 1 与 Rails 3 一起使用 并且我的布局中有以下闪存处理代码 我登录我的应用程序 Flash 说 Signed in successfully 然后注销 然后错误登录并闪烁显示 Signed out s