rails在其他控制器出错后呈现表单

时间:2013-04-21 15:26:56

标签: ruby-on-rails-3 controller render

我在以下关联中有两个模型:客户has_many产品和Product belongs_to客户端。在客户端显示视图中,我提供了一个表单来创建新产品,该表单自动属于当前客户端。客户端控制器中的show方法

def show
  @client    = Client.find(params[:id])
  @products  = @client.products.paginate(page: params[:page])
  @product = @client.products.new
  @product.client_id = @client.id
end

并且show视图呈现部分

    <h1>New Product:</h1>
    <%= render 'shared/product_form' %>

这样可以正确创建产品。

发生验证错误时,我在产品创建方法中设置了一个闪存,并将redirect_重定向到客户端显示页面。在那里,我放松了正确填写的数据。我尝试保存@product实例变量,该变量包含所有数据(包括错误的字段)

render client_path(client) 
来自产品控制器的

,但会产生错误

  

缺少模板/客户端/ 17

地址为

http://localhost:3000/products

我说错了吗?我知道渲染通常会渲染同一个控制器的动作。我可以以某种方式从产品控制器渲染Client :: show吗?是否有其他方法可以保存用户输入的数据?

3 个答案:

答案 0 :(得分:5)

如果发生验证错误,您应该重定向回生成验证错误的页面。即:如果用户在提交表单时处于products/new,那么您的products#create操作应以render :new结束,以再次展示产品表单。

如果您的products#create操作是从clients#show收到表单,那么您确实希望使用验证错误呈现clients#show。在这种情况下,表单中填写的所有信息都将在params[:product]处提供,就像它进入products#create一样。

你可能想看看我最近写的another answer来了解控制器之间的流程。

具体而言,您案件中的误解如下:

如果您遇到验证错误,则记录将无法保存,因此您无法“返回该数据”,因为您的应用尚未将其保留在任何位置。提交的唯一数据副本位于请求中。

如果您重定向您没有转发请求,则通过向其他URL发出新请求来响应初始POST请求(其中包括所有表单信息为params [:product])。这就是你想使用RENDER的原因。

但是,如果您尝试render clients_path(client),Ruby会首先评估clients_path(client)到字符串clients/(client.id),或者您给出的示例clients/17。< / p>

然后渲染尝试调用您没有模板的render 'clients/17'。它正在寻找一个名为clients/17.html.erb的文件。这就是你得到错误的原因。

总而言之,总结一下,您的products#create操作会收到从表单发送的信息params[:products]。该控制器操作之外的信息不可用。因此,如果存在验证错误,而不是创建产品,则此控制器操作应呈现用户最初来自的相同页面(通常为products/new),以便他们可以看到他们刚刚拥有的表单(使用如果您正在使用表单构建器,则会将信息填回其中,并且还会看到阻止保存的错误。

我希望这有意义,随时提出后续问题。

答案 1 :(得分:0)

是的,你说错了。

有三个问题:

  1. render应该呈现模板名称,例如client/newshared/form等。参数不能是路径或变量。该变量由控制器传递给视图,与render无关。

  2. 您不应使用render进行保存失败。即使您使用的模板名称为#1,您最终也会在客户端页面中找到错误的网址products/create。这是不可接受的。

    我的建议是始终使用redirect来保存失败。

  3. 小问题。在控制器中,如果您使用了@product = @client.products.new,则@product对象将使每个属性都为空但具有有效的客户端ID。因此,您无需再次@product.client_id = @client.id分配客户端ID。但这不会影响结果。

答案 2 :(得分:0)

安德鲁的好回答加上这个:
Where to render comments controller in Rails on model validations failure?
使解决方案更加清晰。

您的具体示例:请注意create中的ProductsController操作包含所需的所有实例变量render 'clients/show'