7

据我所知,这是用于编辑和更新资源的标准 rails 模式。

我有一个用于编辑操作的 GET 路由/users/:id/edit和一个用于更新操作的 PUT 和 PATCH 路由/users/:id

这是我的控制器操作:

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 验证),渲染操作正确显示编辑视图,但用户浏览器中的路径从 更改/users/1/edit/users/1

根据我的阅读,这似乎是 rails 的预期行为,但这让我感到困惑,因为我认为 REST 背后的核心思想是 URL 引用资源的规范视图?

如果我redirect_to使用编辑操作而不是renderURL 应该是这样,但是我会丢失表单上的错误消息。

有没有比在使用 redirect_to 之前将错误转储到会话中更明智的方法来保存 URL 和错误消息?如果可以的话,我想避免这种情况。

更新:

我希望 URL 持续存在(以及错误)的原因是因为我正在使用 current_page? 在导航中设置活动状态。因此,如果表单提交错误,菜单中的“编辑”操作将失去突出显示。

4

2 回答 2

1

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

默认情况下,资源的路径与#update相同#show,但请求方法不同GET,而PUT. 因此,当#update呈现 HTML 响应时,它与#show.

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

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

添加

操纵活动状态很容易。我不喜欢current_page?需要太多代码的。使用controller_pathandaction_name代替。

  if controller_path == 'users' && (action_name == 'edit' || 'update') 
     # add active class
  end      
于 2013-09-04T13:35:50.867 回答
0

您应该能够重定向到编辑 URL,并通过替换来避免丢失错误消息

flash.now.alert = "Unable to change account details"

flash.alert = "Unable to change account details"
于 2015-06-25T13:14:20.523 回答