Ruby on rails 是否在浏览器中呈现模板并更改url字符串?

Ruby on rails 是否在浏览器中呈现模板并更改url字符串?,ruby-on-rails,ruby-on-rails-3,Ruby On Rails,Ruby On Rails 3,我有两个动作-编辑和更新。编辑中的表单将值提交到更新操作。当保存模型失败时,我渲染编辑teplate,用户在其中看到错误,并用之前填充的内容预填充字段。在用户浏览器的URL面板中有一个巨大的但对我来说是这样的,其中有/user/update,即使是在(而且是因为)我渲染编辑模板时也是如此。我可以通过在更新操作中向render方法传递一些参数来改变这一点吗?我不希望用户看到除了编辑之外还有任何(更新)操作。有可能吗?有两种方法: 1) 从更新操作重定向回编辑操作,而不仅仅是呈现模板,并传递要用于填

我有两个动作-编辑和更新。编辑中的表单将值提交到更新操作。当保存模型失败时,我渲染编辑teplate,用户在其中看到错误,并用之前填充的内容预填充字段。在用户浏览器的URL面板中有一个巨大的但对我来说是这样的,其中有/user/update,即使是在(而且是因为)我渲染编辑模板时也是如此。我可以通过在更新操作中向render方法传递一些参数来改变这一点吗?我不希望用户看到除了编辑之外还有任何(更新)操作。有可能吗?

有两种方法:

1) 从更新操作重定向回编辑操作,而不仅仅是呈现模板,并传递要用于填充正在编辑的对象的错误消息和属性。这将导致URL为/user/edit

def update @user = User.find(params[:id]) if @user.update_attributes params[:user] ... else redirect_to edit_user_path(@user, :messages => @user.errors) end end def更新 @user=user.find(参数[:id]) if@user.update_属性参数[:user] ... 其他的 重定向到编辑用户路径(@user,:messages=>@user.errors) 结束 结束 2) 发布到编辑操作而不是更新操作,并完全删除更新操作。你可以使用request.post吗?在编辑操作中,检查请求是否为post或get请求,然后使用相同的函数定义执行更新和编辑操作

def edit @user = User.find(params[:id]) if request.post? @user.update_attributes params[:user] ... else ... end end 定义编辑 @user=user.find(参数[:id]) 如果请求,请发邮件? @user.update_属性参数[:user] ... 其他的 ... 结束 结束
注意:请记住,您永远无法对客户端隐藏POST操作,因为客户端可以查看您的源代码并查看您在表单中发布的操作。

这是解决此问题的第三种方法:

在您的routes.rb中

resources :users
match 'users/:id/edit' => 'users#update', :via => :put, :as => :put_user
在您的视图中(例如edit.html.erb)


一个稍微现代一点的版本基于张学良的答案

resources :jobs, except: [:update] do
    member do
        patch 'edit', action: :update, :as => :update_edit
    end
end
这将生成除标准更新路由之外的所有标准restful路由。(如果您不需要所有操作,则可以仅使用
:[]

此外,它还产生

update_edit_job PATCH  /jobs/:id/edit(.:format) 
现在您只需更新表单以指定路径

<%= form_for @job, :url => update_edit_job_path do |f| %>
  ...
<%  end %>

可以使用此处描述的pushState()方法:

例如,您可以将其放入javascript函数中,该函数在发生验证错误时调用:


我想说的是,您还不明白REST是如何工作的,更重要的是,为什么它在Rails中工作,您应该在将自己的想法强加给它之前尝试学习该框架

首先,idomatic rails路由中没有该操作。您可以通过向
things/:id
发送修补程序或PUT请求来执行更新。例外情况是
new
edit
,因为这些操作用于呈现表单

           Prefix Verb   URI Pattern                                                                              Controller#Action
           things GET    /things(.:format)                                                                        things#index
                  POST   /things(.:format)                                                                        things#create
        new_thing GET    /things/new(.:format)                                                                    things#new
       edit_thing GET    /things/:id/edit(.:format)                                                               things#edit
            thing GET    /things/:id(.:format)                                                                    things#show
                  PATCH  /things/:id(.:format)                                                                    things#update
                  PUT    /things/:id(.:format)                                                                    things#update
                  DELETE /things/:id(.:format)                                                                    things#destroy
编辑操作(GET/things/:id/edit)显示用于编辑资源的表单。这是一个幂等操作,因为它应该返回相同的结果,并且不会更改资源

更新操作(PATCH | PUT/things/:id)呈现对资源执行非幂等变换的结果

您还应该注意,Rails中的渲染与重定向无关,这是一个常见的错误概念

render :edit
实际上只是以下的简写:

render "things/edit"
它不调用编辑操作-两者只是共享一个视图,但在概念上是完全不同的操作

重新加载该页面当然不会显示与对
/things/1
的GET请求相同的结果-而不是修补/放置。请记住,GET请求应该始终是幂等的


重定向回将在历史记录中创建一个条目,因为它是一个单独的GET请求,加上您需要将整个表单体作为GET参数传递,这一点并不理想。此外,您基本上抛弃了rails的真正威力,这是您接受其约定所获得的生产力。

在执行选项1时,我最终得到了一个URL类似于
articles/1/edit?消息=/23
,错误不会显示。好的,当然可以,但问题是如果用户的补丁/PUT-to-controller#更新由于一些验证问题而失败,然后您调用
render:edit
URL会变回
/controller/:id
。如果用户点击“刷新”,他们将获得
c的页面OnController#show
。如果他们回到编辑页面,这将更为惯用。@Evan错误-
呈现:编辑
不会更改浏览器URL,因为它不是重定向。当用户单击表单上的提交按钮时,URL已经更改。
呈现:编辑
只是呈现模板并设置响应正文。@Evan您需要更改表单的action属性,使其提交到
/things/1/edit
,这在REST中不是惯用的正确方法。这一切归结为您缺少的幂等性。当然,但是说
render:edit
不会更改url有点迂腐,不是吗?拒绝更新PUT/PATCH的结果用户认为他们应该回到
things/1/edit
重试。我们只是想保留他们已经键入的内容,以便他们可以修改并重试。rails的工作方式是,我们可以重定向到
things/1/edit
或呈现模板(不更改URL)为了保留失败的PUT/PATCH的内容,以便用户可以重试。另外,补丁到
/things/1/edit
如何比补丁到
things/1
的幂等性更低?两者都不是。@evan-你仍然不明白。不,我不会说这有点迂腐,因为大多数新程序员都在努力理解HTT的基础知识P、 客户端/服务器关系。在客户端中单击链接和提交表单发送请求-服务器只是响应。它实际上无法更改浏览器的位置。如果客户端希望跟踪重定向,则由客户端决定。非常重要的目的。
  var url = document.referrer;
  window.history.pushState(null, null, url);
           Prefix Verb   URI Pattern                                                                              Controller#Action
           things GET    /things(.:format)                                                                        things#index
                  POST   /things(.:format)                                                                        things#create
        new_thing GET    /things/new(.:format)                                                                    things#new
       edit_thing GET    /things/:id/edit(.:format)                                                               things#edit
            thing GET    /things/:id(.:format)                                                                    things#show
                  PATCH  /things/:id(.:format)                                                                    things#update
                  PUT    /things/:id(.:format)                                                                    things#update
                  DELETE /things/:id(.:format)                                                                    things#destroy
render :edit
render "things/edit"