Rails 重定向 flash[:notice] 在不应该的时候坚持

Rails redirect flash[:notice] persisting when not supposed to

我有一个带有 redirect_to 的按钮,运行 是我的控制器操作,它为我的模型创建了一个新行。第一次,它正确创建并重定向。重定向后,我通过菜单转到上一页并重复相同的操作。单击该按钮后,它会重定向到正确的页面(它不应该...缓存?),然后显示我之前的闪现消息。所以它是重复的。我放入调试器语句以查看它在第二个 运行 中发生的位置 - 它实际上发生在我的按钮操作执行之前。在 运行 剩下的代码之后,它使用相应的(第二个)flash 正确地重定向(但由于它过早地重定向,重定向到同一页面)。我如何摆脱额外的初始闪现消息?

这是一张展示我的意思的图片:

如果您查看 URL 正下方的蓝色加载条,它表明该页面尚未加载(我使用调试器语句停止了它,如下所示)。但是,重定向和闪存已经发生,这是不应该发生的,因为预期的重定向和闪存将在 turbolinks 完成页面加载后发生。

初始link:

<%= link_to create_wager_from_favorite_wager_path(favorite_wager), data: { confirm: 'Create this wager?' } do %>
  Create Wager
<% end %>

控制器动作:

def create_wager_from
  debugger
  # on second run through, the redirect and flash happens before I reach this point
  @favorite_wager = FavoriteWager.find(params[:id])
  @anchor = params[:anchor]

  set_member_statuses()
  result_message = @favorite_wager.create_wager_from_favorite(current_user)

  respond_to do |format|
      format.html { redirect_to my_wagers_path(:game => @favorite_wager.game), notice: "Wager created successfully!" }
  end
end

此时,它遵循标准路径,我 99% 确定其余代码无关紧要。

我已经尝试在加载带有按钮操作的页面时检查 flash 参数,但它是空的。所以我不确定是什么导致了这个问题。任何见解表示赞赏。

更新:更改为flash.now[:notice] 使重复停止,但仅在第一次单击按钮时才显示闪烁。然后它不会在任何时候出现。并且刷新页面会导致错误重现。

阅读 Turbolinks 后,我确定导致此问题的原因是 turbolinks 中称为 "page preview" 的自然内置功能。在这里它将在服务器响应到达之前将先前缓存的页面显示为某种 "preview",这给人一种页面已经加载的错觉。

但是,在我的例子中缓存的重定向页面在它被提供的那一刻就被缓存了,这意味着闪存消息也被捕获到该缓存中。所以在我第二次点击创建按钮时,它会加载带有 Flash 的缓存页面,然后重新定向为真实的并再次 Flash(就像它所支持的那样)。

所以这里的解决方案是a。禁用所有页面预览或 b。为特定 link 禁用 turbolinks。我选择了b。因为它不会影响我程序的其余部分,代价是蓝色加载动作不再存在。下面是解决方案(非常简单):

之前:

<%= link_to create_wager_from_favorite_wager_path(fw, :anchor => anchor), data: { confirm: 'Create this wager?' }, class: "red-btn create-favorite-wager-btn" do %>
  Create Wager
<% end %>

之后:

<%= link_to create_wager_from_favorite_wager_path(fw, :anchor => anchor), data: { confirm: 'Create this wager?' }, "data-turbolinks": "false", class: "red-btn create-favorite-wager-btn" do %>
  Create Wager
<% end %>

要防止元素在缓存页面(包括预览)中可见,请删除 turbolinks:before-cache 上的元素。例如,您可以在主应用程序 JavaScript 文件中包含这样的内容:

addEventListener('turbolinks:before-cache', () => {
  document.querySelectorAll('.flash').forEach(element => element.remove())
})

有关此结帐的更多信息https://github.com/turbolinks/turbolinks#understanding-caching