首页 > 解决方案 > Rails 重定向或渲染以显示错误

问题描述

当用户对资源发出无效的创建请求时,我想将它们发送回表单并向他们显示错误。据我所知,调用render "new"是标准的方法。

这对我来说似乎是个坏主意,因为创建请求已将用户带到 /resources,而我的“新”表单位于 /resources/new。如果我使用render "new",地址栏中的 URL 将不会反映用户看到的内容。如果他们在那里发出 GET 请求,他们最终会出现在不同的页面上。

我以为我可以通过使用来解决这个问题redirect_to new_[resource]_path,但如果我这样做,我将无法访问表单数据和错误。当然,这不是一个罕见的问题。有没有更好的方法来处理它?

我对编辑/更新和其他表单/提交操作对有同样的问题。

标签: ruby-on-rails

解决方案


TL;博士:

class ResourcesController < ApplicationController
  def new
    @resource = Resource.new(resource_params)

    if resource_params.present?
      @resource.validate
    end
  end

  def create
    @resource = Resource.new(resource_params)
    if @resource.save
      redirect_to @resource, notice: 'Resource has been created'
    else
      redirect_to new_resource_url(resource: resource_params)
    end
  end

  private

  def resource_params
    params.fetch(:resource, {}).permit(...)
  end
end

在我早期的初学者日子里,我自己也问过这个问题,为什么 Rails 脚手架生成器def create会在保存失败时生成操作render :new,而不是像上面那样重定向到正确的 URL,这会使用户感到困惑,因为他们的 URL 会从更改/resources/new/resources即使他们仍然会在页面上看到完全相同的资源表单,因此他们将无法重新加载页面或复制此/resourcesURL(例如,如果他们想将此 URL 共享给其他人),因为他们应该共享此/resourcesURL,其他人将在页面上看到资源列表,而不是原始用户期望从复制的 URL 中看到的内容:这是表单页面。

用户提交表单后,他们在地址栏上看到的 URL 应该已经变成了POST http://localhost:3000/resources,而不仅仅是简单的http://localhost:3000/resources. 浏览器隐藏了正在使用的 HTTP 方法,这就是为什么这会导致它们可能的混淆,/resources有时似乎两者兼而有之:表单页面,有时是资源列表页面。但是,说到用户体验,每当有人在浏览器的 URL 地址栏中输入或粘贴某些内容时,总是自动暗示在进行GET请求。GET因此,浏览器开发人员只需简单地向用户隐藏 HTTP 方法(即特别是)以免混淆他们是有意义的。

从我上面的回答中,我以前只使用过一次这样的东西(因为有一个特定的操作要求我不要从推荐人表单页面更改 URL)。但是,我通常render :new而不是redirect_to new_resources_url,仅仅是因为:

  • aredirect_to new_resource_url(resource_params)将花费两倍的时间和数据传输比简单的呈现:new。为什么?因为无论如何您都使用完全相同的参数重定向(打开一个新请求)。试想一下,如果您的表单页面很大,并且有很多输入字段。

  • 并且 URL 的长度是有限制的,如果您的表单很大且文本字段很长,则不能保证有效。看到这个

更新:

正如您所说,为什么不只是在提交表单时POST /resources/new代替,对吧?POST /resources这将解决redirect_to new_resource_url(resource_params)我上面显示的问题,因为 form-submit 之后的 URL 将是相同的,您可以简单地render :new, 然后。我实际上同意这一点,而且我在很久以前也使用过类似的东西。我不使用它的主要原因是它不符合 REST 标准。也就是说:POST /resources/new意味着您正在“内部”resources/new位置创建一个 Resource 对象,这意味着通过 REST,在提交表单后,我将并且应该能够通过执行类似的操作来访问这个新创建的资源GET /resources/new/the_newly_created_record,除了.. . 你不能。

但是您仍然可以使用POST /resources/new,尽管我不建议在像您这样的普通 Rails 应用程序上使用它,但在基于 API 的 Rails 应用程序上严格不鼓励它。


推荐阅读