Rails 当前视图中的渲染表单错误

Rendering form errors in the current view in Rails

我有一个 MainPagesController 索引页,它呈现来自具有表单的 QuotesController 的 'new' 页面。如何呈现带有表单错误的 MainPagesController 索引页?

MainPages/index

<h1>Welcome to Book Quotes</h1>
<p>
  Post your favourite quotes from your favourite books
  <%= render 'quotes/new' %>
</p>
<%= render 'quotes/all_quotes' %>

Quotes/new

<h1>Add a quote</h1>
<%= render 'quotes/form' %>

Quotes/_form

<%= form_for @quote do |f| %>
  <% if @quote.errors.any? %>
    <ul>
    <% @quote.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  <% end %>
  <p>
    <%= f.label :passage %><br>
    <%= f.text_field :passage %>
  </p>
  <p>
    <%= f.label :book_title %><br>
    <%= f.text_field :book_title %>
  </p>
  <p>
    <%= f.label :book_author %><br>
    <%= f.text_field :book_author %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

QuotesController

def create
  @quote = Quote.new(quote_params)
  if @quote.save
    redirect_to root_url
  else
    render #not sure what goes here
  end
end

由于您要处理的表单是嵌套表单,render :new 的标准建议在这里对您没有帮助。相反,您可以将用户重定向回索引页面,通过 Flash 传递错误,并更新您的视图以处理显示这些错误。

(只是一个想法:让这个动作由 AJAX 提供支持可能值得研究。用户体验可能会更好,并且它会简化您的代码设计。)

无论如何,在您的 QuotesController 中,#create 操作需要记录错误并在将用户重定向回错误来源时传递它们:

def create
  @quote = Quote.new(quote_params)
  if @quote.save
    redirect_to root_url
  else
    flash[:quote_errors] = @quote.errors.full_messages
    redirect_to :back # or main_pages_path
  end
end

然后,您的 Quotes/_form 视图需要处理这些错误:

<%= form_for @quote do |f| %>
  <% if flash[:quote_errors] %>
    <ul>
    <% flash[:quote_errors].each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  <% end %>
  # ...

现在,这有点难看。您可能想知道——难道我们不能通过 Flash 将 @quote 对象传回,这样视图就不必改变了吗?但是,尽管这在技术上是可行的,但将对象序列化到会话中是一条危险的道路。我建议避免使用它。

另一种选择是不在 QuotesController 上而是在您的 MainPages 控制器上使报价提交成为一个动作。例如,

class MainPagesController < ApplicationController
  def index
    # ...
  end

  def create_quote
    @quote = Quote.new(quote_params) # need to move quote_params in, too
    if @quote.save
      redirect_to root_url
    else      
      render :index
    end
  end
  # ...

这允许从您的表单访问 @quote 实例变量,因此错误处理将正常工作。不是很RESTful,但话又说回来,大多数前端网站流量也不是。