如何在从更新操作呈现编辑操作时阻止rails更改路径

时间:2013-09-04 13:23:38

标签: ruby-on-rails

据我所知,这是用于编辑和更新资源的标准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?在导航中设置活动状态。因此,如果提交的表单有错误,菜单中的“编辑”操作将失去突出显示。

2 个答案:

答案 0 :(得分:1)

您在/users/1的原因是视图由#update呈现,而不是#edit

默认情况下,#update的路径与#show的路径相同,使用不同的请求方法GETPUT。因此,当#update呈现HTML响应时,它与#show相同。

我认为结果是可以接受的,无论你在预期的结果是什么路径。正如您已经发现的那样,如果使用redirect@user实例将更改为分支新实例,从而丢失错误和以前的填充。

路径上有解决方法,例如使用会话传递实例变量,但我认为这不值得。目前的结果还不错。

添加

操纵活动状态很容易。我不喜欢需要太多代码的current_page?。请改用controller_pathaction_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"