当用户对资源进行无效的创建请求时,我想将其发送回表单并向他们显示错误。据我所知,调用render "new"
是实现此目的的标准方法。
这对我来说似乎是个坏主意,因为创建请求已将用户带到/ resources,而我的“新”表单则位于/ resources / new。如果我使用render "new"
,则地址栏中的URL不会反映用户看到的内容。如果他们在那里提出GET请求,那么他们将进入另一个页面。
我认为可以使用redirect_to new_[resource]_path
解决此问题,但是如果这样做,我将无法访问表单数据和错误。当然,这不是一个罕见的问题。有没有更好的方法来解决它?
编辑/更新和其他表单/提交操作对存在相同的问题。
答案 0 :(得分:1)
您可能想得太多。 get /resources
索引页与post /resources
的create操作怎么样?地址栏中的网址相同!
这不是问题。既不是技术问题也不是美学问题。
render "new"
的意思是:渲染此模板,而不是:转到此路线。尽管模板通常具有相应操作的名称,但这不是必需的。
答案 1 :(得分:1)
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
,因此他们将无法重新加载页面或复制此/resources
URL(例如,如果他们想与其他人共享此URL),因为他们应该共享此/resources
URL,其他人将在页面上看到资源列表,而不是原始用户希望从复制的URL:表单页面中看到。
用户提交表单后,他们在地址栏上看到的URL应该已更改为POST http://localhost:3000/resources
,而不仅仅是http://localhost:3000/resources
。浏览器隐藏了正在使用的HTTP方法,这就是为什么这可能导致他们混淆/resources
有时有时是这样的原因:表单页面,有时是资源列表页面。但是,说到UX,每当有人输入任何内容或在浏览器的URL地址栏中粘贴一些内容时,总是会自动暗示它正在执行GET
请求。因此,对于浏览器开发人员来说,仅向用户隐藏HTTP方法(特别是GET
)就很有意义,以免混淆他们。
根据我上面的回答,我以前只使用过一次这样的操作(因为有某些操作要求我不要从引荐来源网址表单页面更改网址)。但是,我通常是render :new
而不是redirect_to new_resources_url
,仅仅是因为:
redirect_to new_resource_url(resource_params)
所花费的时间和数据传输量比仅渲染:new
所花费的时间要多一倍。为什么?因为无论如何您使用完全相同的参数重定向(打开一个新请求)。试想一下,如果您的表单页面太大,并且有很多输入字段。
,而且URL的长度是有限制的,如果您使用非常大的表单且文本字段很长,则不能保证可以正常使用。看到这个SO
尽管您已经说过,为什么在提交表单时不只是POST /resources/new
而不是POST /resources
,对吗?这将解决我上面显示的redirect_to new_resource_url(resource_params)
问题,因为提交表单后的URL将会是相同的,然后您只需简单地render :new
即可。我实际上对此表示同意,并且很久以前我也使用过类似的方法。我不使用它的主要原因是它不符合REST标准。也就是说:POST /resources/new
意味着您正在resources/new
位置“内部”创建一个资源对象,这意味着通过REST,在提交表单之后,我将并且应该能够访问此新创建的对象通过执行GET /resources/new/the_newly_created_record
之类的资源,除了...您做不到。
但是您仍然可以使用POST /resources/new
,尽管我不建议在像您这样的普通Rails应用程序上使用它,但是严格建议不要在基于API的Rails应用程序上使用它。