2011-02-18 44 views
9

我是rails新手,我不确定我是否同意我在某些教程中完成的工作。这个问题与如何处理无效表单提交有关。做事的标准方法似乎是:在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 

当@ thing.save失败,用户呈现相同的形式,预填出与他刚输入的值,随着什么地方闪光错误。到目前为止,除了现在URL已经从/ things/new变成了things /之外,其他人都期望渲染索引视图。

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

我意识到RESTfully,这个方法可能是“正确的”,因为事物对象的创建应该是POST/to事件的结果,但用户界面明智的,我并不特别关心它。

我可以“手动”将无效的@thing对象保存在用户的会话中,以便在将他重定向回new_thing_path之后显示,但感觉像是一个黑客。这似乎应该有一个“轨道”来做到这一点。

想法?

+0

我对Rails核心的投诉完全一样,但你比我更好地表达了它:)好问题。 – Andrew 2011-04-03 03:35:09

回答

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"} 

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

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"} 

虽然不建议,你可以得到这个结果与下列路线:

resources :things, :except => [ :create ] do 
    post "create" => "things#create", :as => :create, :path => 'new', :on => :collection 
end 

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

所有这些都说了,你在你的问题中的URL描述听起来不对。你列出以下内容:提交新thing(在/things/new提交表单),

  1. /things/new的网址更改为/things
  2. 点击回提示重新提交表格后
  3. 刷新显示things#index

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

  1. /things/new的网址更改为/things(这是相同的)
  2. 点击回将用户回后非 -submitted形式(重后不请求)
  3. 刷新提示重新提交表单(如预期在我看来)
+1

谢谢布兰登。这很有帮助,但我仍然不在乎默认功能。我想我只会使用JavaScript验证,以尽可能避免它。 – dearlbry 2011-02-21 16:38:06

0

我知道这是一个老问题,但最近我一直在玩的一种方法是使用AJAX提交表单,即使它不需要它。这可以让您将其提交到默认的创建/更新操作,只要路由通过,但浏览器中的URL不会更改。通过指向/ index页面的链接或者在成功保存时重定向到的位置,或者数据无效时出现错误消息的“400错误请求”,响应可以是成功的简单200。

最大的缺点是错误消息和无效字段的显示现在完全是您的客户端JavaScript的责任。这变成了一个小得多的问题,一旦你在客户端使用了Backbone或KnockoutJS之类的东西,它甚至会成为一件好事。

相关问题