在Rails中处理无效表单提交的正确方法

dea*_*bry 9 ruby-on-rails-3

我是rails的新手,我不确定我是否同意我在一些教程中所做的事情.该问题与如何处理无效的表单提交有关.做事的标准方式似乎是:

class ThingsController < ApplicationController


  # POST /things
  def create

    @thing = Thing.new(params[:thing])

    if @thing.save
      flash[:notice] = 'Thing created'
      redirect_to(@thing)
    else
      render :action => :new
    end

  end
Run Code Online (Sandbox Code Playgroud)

当@ thing.save失败时,将向用户显示相同的表单,预填充其刚刚输入的值,以及出现错误的闪存.到目前为止一切都那么好,除了现在URL已从/ things/new更改为things /,而人们期望将其呈现为索引视图.

此外,如果用户刷新页面,他现在正在查看索引视图.如果他点击回来,他会被提示重新提交表格,我一直试图避免.如果我redirect_to(new_thing_path),用户以前的提交将丢失,错误消息也将丢失.

我意识到RESTful,这个方法可能是"正确的",因为事物对象的创建应该是POST到/ thing的结果,但是用户界面方面,我并不特别关心它.

我可以"手动"在用户会话中保存无效的@thing对象,在我将其重定向回new_thing_path之后显示,但这感觉就像是黑客.似乎应该有一种"轨道方式"来做到这一点.

想法?

Mic*_*ley 3

正如您所发现的,默认情况下,当您指定 时resources :things,用于创建新事物的 POST 路径位于/things。这是 的输出rake routes

    things GET    /things(.:format)          {:action=>"index", :controller=>"things"}
           POST   /things(.:format)          {:action=>"create", :controller=>"things"}
 new_thing GET    /things/new(.:format)      {:action=>"new", :controller=>"things"}
edit_thing GET    /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"}
     thing GET    /things/:id(.:format)      {:action=>"show", :controller=>"things"}
           PUT    /things/:id(.:format)      {:action=>"update", :controller=>"things"}
           DELETE /things/:id(.:format)      {:action=>"destroy", :controller=>"things"}
Run Code Online (Sandbox Code Playgroud)

听起来你想要更像这样的东西:

create_things POST   /things/new(.:format)      {:action=>"create", :controller=>"things"}
       things GET    /things(.:format)          {:action=>"index", :controller=>"things"}
    new_thing GET    /things/new(.:format)      {:action=>"new", :controller=>"things"}
   edit_thing GET    /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"}
        thing GET    /things/:id(.:format)      {:action=>"show", :controller=>"things"}
              PUT    /things/:id(.:format)      {:action=>"update", :controller=>"things"}
              DELETE /things/:id(.:format)      {:action=>"destroy", :controller=>"things"}
Run Code Online (Sandbox Code Playgroud)

虽然不推荐,但您可以通过以下途径获得此结果:

resources :things, :except => [ :create ] do
  post "create" => "things#create", :as => :create, :path => 'new', :on => :collection
end
Run Code Online (Sandbox Code Playgroud)

您还需要修改表单以使它们 POST 到正确的路径。

话虽如此,您问题中的网址描述听起来并不正确。您列出以下内容: 提交新的thing(在 提交表格/things/new)后,

  1. URL 更改/things/new/things
  2. 点击返回提示重新提交表单
  3. 令人耳目一新的节目things#index

不是我在自己的 Rails 3 应用程序中体验到的功能。相反,我发现:提交新的thing(在 提交表格/things/new)后,

  1. URL 从 变为/things/new/things这是相同的)
  2. 单击“返回”将使用户返回到提交的表单(不请求重新发布)
  3. 刷新提示重新提交表单(正如我认为的那样)