Ruby on rails 处理REST中无效的PUT/POST导致的UX混乱的最佳方法?

Ruby on rails 处理REST中无效的PUT/POST导致的UX混乱的最佳方法?,ruby-on-rails,rest,Ruby On Rails,Rest,我的堆栈是Rails,但问题实际上与框架无关 REST方法论认为 要查看现有用户的编辑表单,请执行以下操作: GET: users/:id/edit PUT: users/:id 要更新现有用户,请执行以下操作: GET: users/:id/edit PUT: users/:id 这对验证错误意味着什么 这一切都是合理的,除非表单无法验证。当表单未验证时,您最终访问的URL不是users/:id/editURL,而是: users/:id 这导致了两个问题。一个是导航,另一个是用户刷

我的堆栈是Rails,但问题实际上与框架无关

REST方法论认为

要查看现有用户的编辑表单,请执行以下操作:

GET: users/:id/edit
PUT: users/:id
要更新现有用户,请执行以下操作:

GET: users/:id/edit
PUT: users/:id
这对验证错误意味着什么

这一切都是合理的,除非表单无法验证。当表单未验证时,您最终访问的URL不是
users/:id/edit
URL,而是:

users/:id
这导致了两个问题。一个是导航,另一个是用户刷新表单时发生的情况:

新的编辑表单:

相同的表单有错误-尽管URL和nav表明我们在不同的地方

从视觉上看,页面现在很混乱,因为导航和URL表明用户不在编辑表单上,而是在
资源#show
页面上

用户现在刷新表单时看到的内容-一个完全不同的页面

它还有其他含义。如果用户感到沮丧,只想重新设置表单,他们的本能是刷新页面。如果他们这样做,他们会在
资源#显示
页面而不是
资源#编辑
页面上找到自己

天真的是,我们可能会将无效提交重定向回
资源#edit
URL。如果我们这样做的话(在Rails中默认情况下),我们将无法以他们刚刚提交的形式向他们显示错误,因为这些错误存储在内存中

可能的解决方案

据我所知,有两种方法可以解决这个问题:

  • PUT users/:id
    验证失败时:序列化
    user
    对象并将其存储在会话中。重定向到
    GET users/:id/edit
    ,然后在下一页取消序列化对象以显示错误-感觉混乱
  • 更改路由,使
    PUT
    转到
    users/:id/edit
    ,而不是
    users/:id
    ——也会感到凌乱
  • 问题


    解决这个问题最合适的方法是什么?我觉得序列化方法可能最有意义,但因为它不是Rails核心的一部分,我觉得我遗漏了一些东西。我知道我不是第一个解决这个问题的人,并且对其他人的方法感兴趣

    首先,这是rails应用程序开箱即用的典型行为

    如果有人提交了一个无效的表单,然后刷新页面,会发生什么?在您看到的典型rails应用程序中,我们只是刷新,并且(在更新记录的情况下)可能会将它们从用户体验中弹出。依我看,没关系。刷新有时会破坏网络:)

    当设计人员想要更改“无效”页面的样式,或者开发人员正在查看错误页面上的呈现错误时,通常会出现这种情况,他们修复代码或css,然后刷新页面,可能希望看到页面得到修复,但相反,他们可能会得到与/plumbers不接受get请求相关的错误信息,或者他们会被放回plumbers#index页面

    简短的回答通常是,这在大多数rails应用程序上并不是什么大问题,它是这样做的,这样我们就不必依靠在会话中临时存储他们的答案和错误来重定向回编辑页面,所有这些都在一个请求和响应周期内完成

    如果你想改变这种行为,你可以做如下的事情

     class PlumbersController
        def update 
           plumber = Plumber.find(params[:id]) 
           if plumber.update(params[:plumber])
              redirect_to(plumbers_path, :message => "successfully updated!")
           else 
             flash[:plumber_attributes] = params[:plumber]
             redirect_to plumber_edit
           end
        end
        def edit
           @plumber = Plumber.find(params[:id])  
           @plumber.assign_attributes(flash[:plumber]) if flash[:plumber.present?]
        end
      end
    
    注意:此代码尚未测试。一般的想法是将水管工属性弹出到flash中,并重定向到水管工编辑URL


    也就是说,您所描述的行为是典型的,rails绕过它的唯一方法是依赖会话(flash)来实现应用程序逻辑,而它选择不开箱即用。

    这里也没有令人满意的答案,但请看,这也是我得出的相同结论。谢谢你把它记录下来。我投了更高的票。