据我所知,这是用于编辑和更新资源的标准rails模式。
我在/users/:id/edit
上有编辑操作的GET路由以及/users/:id
上的更新操作的PUT和PATCH路由。
以下是我的控制器操作:
def edit
@user = User.find params[:id]
end
def update
@user = User.find params[:id]
if @user.update_attributes(user_params)
redirect_to @user, success: "Changes saved"
else
flash.now.alert = "Unable to change account details"
render :edit
end
end
我在我的部分形式中使用默认的form_for:
<%= form_for @user do |f| %>
在html中创建以下表单:
<form accept-charset="UTF-8" action="/users/1" id="edit_user_1" method="post">
...
<input name="_method" type="hidden" value="patch">
当对update_attributes
的调用成功时,正在重定向用户,但是当调用失败时(由于ActiveRecord验证),渲染操作会正确显示编辑视图,但用户浏览器中的路径将从{更改{1}}至/users/1/edit
。
从我看过的内容看来这是rails的预期行为,但这似乎让我感到困惑,因为我认为REST背后的核心思想是URL是指资源的规范视图?
如果我/users/1
编辑操作而不是redirect_to
,那么网址应该是,但是我丢失了表单上的错误消息。
在使用redirect_to之前,是否有更明智的方法来保留URL和错误消息,而不是将错误转储到会话中?如果可以,我想避免这样做。
更新
我希望URL保持(以及错误)的原因是因为我正在使用current_page?在导航中设置活动状态。因此,如果提交的表单有错误,菜单中的“编辑”操作将失去突出显示。
答案 0 :(得分:1)
您在/users/1
的原因是视图由#update
呈现,而不是#edit
。
默认情况下,#update
的路径与#show
的路径相同,使用不同的请求方法GET
和PUT
。因此,当#update
呈现HTML响应时,它与#show
相同。
我认为结果是可以接受的,无论你在预期的结果是什么路径。正如您已经发现的那样,如果使用redirect
,@user
实例将更改为分支新实例,从而丢失错误和以前的填充。
路径上有解决方法,例如使用会话传递实例变量,但我认为这不值得。目前的结果还不错。
操纵活动状态很容易。我不喜欢需要太多代码的current_page?
。请改用controller_path
和action_name
。
if controller_path == 'users' && (action_name == 'edit' || 'update')
# add active class
end
答案 1 :(得分:0)
您应该能够重定向到编辑网址,并通过替换
来避免丢失错误消息flash.now.alert = "Unable to change account details"
与
flash.alert = "Unable to change account details"