【问题标题】:Validation messages after redirect重定向后的验证消息
【发布时间】:2013-04-19 14:43:58
【问题描述】:

我们有一个表单可以在我们的views/restaurants/show.html.erb 中提交某个餐厅的评分。如果出现验证错误,我们会被重定向回views/restaurants/show.html.erb,但不会出现验证消息。我们发现这是因为我们在 RatingController 创建操作中使用 redirect_to(@restaurant) 丢失了消息。但是我们怎样才能在没有重定向的情况下返回呢?

谢谢!

【问题讨论】:

  • 如果我的回答没有达到重点,请发布更多详细信息
  • @fl00r 的答案就是您要找的!

标签: ruby-on-rails validation redirect


【解决方案1】:

这是我解决这个问题的方法。 (请注意,在接下来的内容中,我显然只包括最相关的行。)

在模型中可能有多个验证,甚至可能报告多个错误的方法。

class Order < ActiveRecord::Base
  validates :name, :phone, :email, :presence => true
  def some_method(arg)
    errors.add(:base, "An error message.")
    errors.add(:base, "Another error message.")
  end
end

同样,控制器动作可能会设置闪现消息。最后,用户可能已经在输入字段中输入了数据,我们希望它也通过redirect_to 持久化。

class OrdersController < ApplicationController
  def create
    @order = Order.new(params[:order])
    respond_to do |format|
      if @order.save
        session.delete(:order) # Since it has just been saved.
      else
        session[:order] = params[:order]  # Persisting the order data.

        flash[:notice] = "Woohoo notice!" # You may have a few flash messages
        flash[:alert] = "Woohoo alert!"   # as long as they are unique,
        flash[:foobar] = "Woohoo foobar!" # since flash works like a hash.

        flash[:error] = @order.errors.to_a # <-- note this line

        format.html { redirect_to some_path }
      end
    end
  end
end

根据您的设置,您可能需要也可能不需要将模型数据(例如 order)保存到会话中。我这样做是为了将数据传回原始控制器,从而能够再次在那里设置订单

无论如何,为了显示实际的错误和闪烁消息,我执行了以下操作(在 views/shared/_flash_messages.html.erb,但您可以在 application.html.erb 或其他任何对您的应用有意义的地方执行此操作)。这要归功于flash[:error] = @order.errors.to_a这一行@

<div id="flash_messages">
  <% flash.each do |key, value|

    # examples of value: 
    # Woohoo notice!
    # ["The server is on fire."]
    # ["An error message.", "Another error message."]
    # ["Name can't be blank", "Phone can't be blank", "Email can't be blank"]

    if value.class == String # regular flash notices, alerts, etc. will be strings
      value = [value]
    end

    value.each do |value| %>
      <%= content_tag(:p, value, :class => "flash #{key}") unless value.empty? %>
    <% end %>
  <% end %>
</div><!-- flash_messages -->

需要明确的是,通知、警报等常规 Flash 消息将是字符串,但错误将是数组,因为上述调用是 errors.to_a

【讨论】:

    【解决方案2】:

    您可以通过 Flash 消息传递您的错误

    flash[:error] = @restaurant.errors
    

    在您需要在重定向中显示之后

    【讨论】:

    • 你的意思是 flash[:error] = @rating.errors?这就是我在 RatingsController 创建操作中的内容: if @rating.save ... else flash[:error] = @rating.errors format.html { redirect_to(@restaurant) } end 这就是我尝试打印它们的方式在views/restaurants/show.html.erb: ...但什么也没有出现。有什么问题吗? (我也试过@rating.errors)。我是新手。谢谢!
    • 你需要把它添加到你的 /app/views/layouts/application.html.erb "flash_#{name}" %>。这样,您的所有 Flash 消息都将正确呈现
    • 如果表单有一些输入,这可能会导致 CookieErrorOverflow
    • @damoiser 仅当会话保存在 CookieStore 中时。如果会话以其他方式保存,则不会引发错误。所有闪存都保存在会话中。
    【解决方案3】:

    这是我仍然做重定向的方法:

    就在您将控制器中的验证错误重定向到闪存之前,就像@shingara 建议的那样:

    if @restaurant_rating.save
      redirect_to @restaurant, :notice => "Successfully added rating to restaurant."
    else
      flash[:error] = @restaurant_rating.errors
      redirect_to @restaurant, :alert => "There were errors to add rating to restaurant. " 
    end
    

    然后在您的评级表单中,您在呈现表单之前为评级对象分配错误:

    - flash[:error].messages.each {|error| @restaurant_rating.errors.add(error[0], error[1][0]) } if flash[:error]
    = simple_form_for @restaurant_rating do |f|
      ....
    

    【讨论】:

      【解决方案4】:

      您可以使用render 代替redirect_to

      render :action => "show"
      

      或再次设置flash[:error]flash[:notice],因为它们会自动重置

      【讨论】:

        【解决方案5】:

        在您在评论中澄清后,您需要设置您的

        /app/views/layouts/application.html.erb

        用这条线

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

        【讨论】:

          猜你喜欢
          • 2016-10-11
          • 1970-01-01
          • 1970-01-01
          • 2012-12-12
          • 1970-01-01
          • 2015-12-18
          • 2020-05-31
          • 2011-11-08
          相关资源
          最近更新 更多