Rails flash hash过早地呈现一个请求

时间:2012-01-10 00:00:06

标签: ruby-on-rails ruby

我在Rails 3中遇到了一个问题,即flash hash似乎过早地返回了一个请求。也就是说,它似乎返回渲染时在同一个请求中设置的东西。例如,考虑执行以下操作的控制器操作:

    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发生时,它们根本不显示。

3 个答案:

答案 0 :(得分:0)

flashflash.now都会呈现,但flash.now会立即执行此操作,而普通旧flash仅在重定向后呈现。

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

根据您的主要问题,您似乎想要使用flash代替flash.now

答案 1 :(得分:0)

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

另一方面,我们仅使用flash[] 新操作 (1) - &gt; 创建操作(我们设置{{ 1}} var)(2) - &gt; 索引操作我们会显示flash[]。和第一个例子中的params一样,我们在第二步之后丢失了flash[]

抱歉我的英语非常糟糕,特别是长篇文章。

答案 2 :(得分:0)

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

似乎如果没有为flash中的键分配新值,那么该键的值将在NEXT请求中为nil。这似乎是显而易见的,但其含义很微妙,因为我在每个请求上使用|| =(“or-equals”)为键分配值。

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

在第一个请求中,flash是一个空哈希。它不包含任何键,因此|| =分配一些。

在第二个请求中,flash是一个带有三个键的哈希值,每个键都是一个空数组。现在,由于每个键都有一个值,|| =不会分配任何内容。这意味着在第三个请求中,rails已经清除了这些值,而flash又是一个空哈希值。

现在,考虑一下这个案例:

在第一个请求中,以空哈希闪存。它不包含任何键,因此|| =分配一些。

在第二个请求中,flash是一个带有三个键的哈希值,每个键都是一个空数组。现在,一个动作调用add_error。但是,闪存[:warnings] 中已存在一个数组。因此,一个值被推入该数组。数组的内容已更改,但flash [:warnings]的值未更改 - 它仍然是对同一数组的引用。因此,有两个含义:

  1. 在此操作过程中,flash [:warnings]的值(即对数组的引用)没有改变,因为我们修改了与rails分配给flash的相同对象[:警告]在请求开始时,它会在渲染时使用新推送的消息进行渲染。
  2. 在此操作期间,flash [:warnings]的值(即对数组的引用)没有改变,因此下一个请求提示的操作根本不会在flash中显示:warnings键。
  3. 因此,总而言之,微妙的一点是为闪存哈希中的键分配新值是导致它在以下请求中可用的原因。

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