在浏览器中渲染模板并更改网址字符串?

时间:2011-01-16 19:14:17

标签: ruby-on-rails ruby-on-rails-3

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

5 个答案:

答案 0 :(得分:6)

以下是第三种方法:

在你的routes.rb

resources :users
match 'users/:id/edit' => 'users#update', :via => :put, :as => :put_user

在您的视图中(例如edit.html.erb)

<%= form_for @user, :url => put_user_path do |f| %>
  ...
<%  end %>

在您的控制器中(例如users_controller.rb)

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    ...
  else
    render 'edit'
  end
end

答案 1 :(得分:2)

有两种解决方法:

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

2)发布到编辑操作而不是更新操作,并完全删除更新操作。你可以使用request.post吗?在您的编辑操作中检查请求是发布请求还是获取请求,然后使用相同的函数定义执行更新和编辑操作。

def edit
  @user = User.find(params[:id])
  if request.post?
    @user.update_attributes params[:user]
    ...
  else
    ...
  end
end

注意:请记住,您无法真正隐藏客户端的POST操作,因为他们始终可以查看您的源代码并查看您在表单中发布的操作。

答案 2 :(得分:1)

我想说的是,您还没有完全理解REST如何在Rails中发挥作用,而更重要的是,您应该尝试学习该框架,然后再施加自己的想法。

首先,在idomatic轨道上没有动作。您可以通过向things/:id发送PATCH或PUT请求来执行更新。 newedit是例外,因为这些操作用于呈现表单。

           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请求相同的结果-不是PATCH / PUT。请记住,GET请求应始终是幂等的。

重定向将在历史记录中创建一个条目,因为它是一个单独的GET请求,加上您需要将整个表单主体作为GET参数传递的事实,这并不理想。另外,您基本上是在放弃使用rails的真正功能,这就是从接受其约定所获得的生产力。

答案 3 :(得分:0)

基于CL Chang回答的更现代的版本

resources :jobs, except: [:update] do
    member do
        patch 'edit', action: :update, :as => :update_edit
    end
end

这将生成所有标准的restful路由,标准更新路由除外。 (如果您不想要所有操作,那么您可以使用only: [<your routes not including :update>]

此外,它会生成

update_edit_job PATCH  /jobs/:id/edit(.:format) 

现在您只需更新表单以指定路径

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

所以,不是通过补丁发送/更新,而是通过补丁转到/ jobs //编辑,这会触及您的更新操作

现在如果出现错误,您可以渲染编辑,并且所有错误都将可见 - 但是用户不会注意到该网址与编辑网址不同(因为只有方法不同)< / p>

def update
  @job = Job.find(params[:id])
  if @job.update_attributes(user_params)
    #redirect somewhere???
  else
    render 'edit'
  end
end

答案 4 :(得分:0)

一个人可以使用此处描述的pushState()方法:https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method

例如,您可以将其放在一个JavaScript函数中,当发生验证错误时,该函数将被调用:

@SpringBootTest // note, no actual configurations specified
public class MyMicroserviceTest {
  ...
}