【问题标题】:Rails flash hash being rendered one request too soonRails flash hash 过早呈现一个请求
【发布时间】:2012-01-10 00:00:06
【问题描述】:

我在 Rails 3 中遇到了一个问题,即闪存哈希似乎过早地返回了一个请求。也就是说,它似乎在渲染时返回了在同一个请求中设置的东西。例如,考虑一个控制器动作:

    add_warning "Danger, will robinson."

在我的 ApplicationController 中,我有:

    before_filter :set_errors
    #...
    def set_errors
      flash[:errors] ||= []
      flash[:warnings] ||= []
      flash[:notices] ||= []
    end
    #...
    def add_warning(msg)
      flash[:warnings] << msg
    end

而我的 application.html.erb 布局模板有

    <% flash[:warnings].each do |msg| %>
      <div class="warnings"><%= msg %></div>
    <% end %>

根据我对 Rails 指南的理解,除非我使用 flash.now,否则不应在同一请求中呈现 flash 内容。而且,如果我有一个redirect_to,它们应该在第二个请求中呈现。但是当 redirect_to 发生时它们根本不会出现。

【问题讨论】:

  • 我不确定你为什么要重新发明轮子。如果您按照应该使用的方式使用闪存(作为会话存储),那么它应该可以正常工作。 guides.rubyonrails.org/…
  • 这正是我想要使用它的方式,除了我想要支持任意数量的多个错误消息。因为该示例只分配了一个字符串,所以它只支持一条错误消息。

标签: ruby-on-rails ruby


【解决方案1】:

flash.now 需要当你不能丢失params[] 例如:用户填写新帖子的表格并且标题错误例如(帖子中的操作new strong> 控制器),他将提交和数据发送到 create 操作,我们有 params[:post][:title] 但如果它无效并且在我们重定向到 new 操作后我们已经没有' t params[:post][:title],我们无法填写字段,用户丢失了所有填写的数据,用户会生气=)在这种情况下,我们使用render,我们仍然需要显示警告,我们使用flash.now。

在其他方式中,我们只使用flash[] new action (1)-> create action(我们设置flash[] var) (2)-> 索引操作我们显示flash[]。就像第一个示例中的参数一样,我们在第二步之后丢失了flash[]。

对不起,我的英语很糟糕,尤其是长文本。

【讨论】:

  • 正如我在 cmets 中对 jstim 的回答所指出的,我没有使用 flash.now。
【解决方案2】:

http://blog.vedanova.com/2010/09/29/rails-flash-now/

根据您的主要问题,听起来您想使用 flash 而不是 flash.now

【讨论】:

  • 不,我不想将数组重置为 nil,因为您不能将字符串推送到 nil 并让它神奇地变成一个数组。
  • 好的,我会更新以保持初始化空数组。您对它们使用 ||= 的原因是什么?如果里面已经有东西,它不会将它们重置为空。
  • 否;从我的示例中可以看出,我从未使用过 flash.new。
  • @fearpi 放松你的语气。 jstim 只是想提供帮助。
  • 您在调用什么操作导致 Flash 渲染过早?我们能看到那个方法吗?我想知道您是否遇到了 :before_filter 的问题。只是猜测
【解决方案3】:

事实证明,问题的原因是 set_errors 方法,加上我对闪存哈希的工作原理缺乏了解。

似乎如果没有为闪存中的键分配新值,则在 NEXT 请求中该键的值将为零。这似乎很明显,但含义很微妙,因为我在每个请求上都使用 ||= ("or-equals") 为键赋值。

考虑我对同一操作有一系列请求的情况,这些请求从未调用 add_warning:

在第一个请求中,flash 是一个空哈希。它不包含键,所以 ||= 分配了一些。

在第二个请求中,flash 是一个包含三个键的散列,每个值都是一个空数组。现在,由于每个键都有一个值,||= 没有分配任何东西。这意味着在第三个请求中,rails 已经清除了这些值,并且 flash 再次是一个空哈希。

现在,考虑这种情况:

在第一个请求中,闪入一个空哈希。它不包含键,所以 ||= 分配了一些。

在第二个请求中,flash 是一个包含三个键的散列,每个值都是一个空数组。现在,一个动作调用 add_error。但是,一个数组已经存在于 flash[:warnings]。因此,将一个值推入该数组。数组的内容已经改变,但 flash[:warnings] 的值没有改变 - 它仍然是对同一个数组的引用。因此,有两个含义:

  1. flash[:warnings] 的值(即对数组的引用)在此操作期间没有改变,因此因为我们修改了 rails 分配给 flash[ 的同一对象: warnings] 在请求开始时,它会在渲染时与新推送的消息一起渲染。
  2. flash[:warnings] 的值(即对数组的引用)在此操作期间没有更改,因此下一个请求提示的操作在 flash 中根本没有 :warnings 键。

因此,总而言之,微妙之处在于为闪存哈希中的键分配新值是导致它在以下请求中可用的原因。

编辑:我想发布我的解决方案可能会有所帮助,即完全消除 set_error 和 before_filter ,而是将 ||= [] 片段放在 add_error 方法中。这样一来,只有在应有的情况下才将值分配给闪存哈希 - 添加错误消息时。

【讨论】:

    猜你喜欢
    • 2011-01-02
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多