Rails 3表单用于自定义操作

时间:2011-01-15 00:00:53

标签: ruby-on-rails forms ruby-on-rails-3 custom-action

我在将表单路由到Rails 3中的自定义操作时遇到问题。以下是我的路由:

resources :photos do
    resources :comments
    collection do
        get 'update_states'
    end
    member do
        put 'upload'
    end
end

这是form_for:

form_for @photo, :remote => true, :url => { :action => upload_photo_path(@photo) }, :html => { :multipart => :true, :method => 'put' } do |f|

这是错误信息:

No route matches {:action=>"/photos/42/upload", :controller=>"photos"}

...这尤其令人沮丧,因为“photos /:id / upload”正是此表单的正确操作。

我错过了什么?

编辑 - 以下是与照片相关的原始路线:

   photo_comments    GET    /photos/:photo_id/comments(.:format)          {:action=>"index", :controller=>"comments"}
                     POST   /photos/:photo_id/comments(.:format)          {:action=>"create", :controller=>"comments"}
   new_photo_comment GET    /photos/:photo_id/comments/new(.:format)      {:action=>"new", :controller=>"comments"}
  edit_photo_comment GET    /photos/:photo_id/comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"}
       photo_comment GET    /photos/:photo_id/comments/:id(.:format)      {:action=>"show", :controller=>"comments"}
                     PUT    /photos/:photo_id/comments/:id(.:format)      {:action=>"update", :controller=>"comments"}
                     DELETE /photos/:photo_id/comments/:id(.:format)      {:action=>"destroy", :controller=>"comments"}
update_states_photos GET    /photos/update_states(.:format)               {:action=>"update_states", :controller=>"photos"}
        upload_photo PUT    /photos/:id/upload(.:format)                  {:action=>"upload", :controller=>"photos"}
              photos GET    /photos(.:format)                             {:action=>"index", :controller=>"photos"}
                     POST   /photos(.:format)                             {:action=>"create", :controller=>"photos"}
           new_photo GET    /photos/new(.:format)                         {:action=>"new", :controller=>"photos"}
          edit_photo GET    /photos/:id/edit(.:format)                    {:action=>"edit", :controller=>"photos"}
               photo GET    /photos/:id(.:format)                         {:action=>"show", :controller=>"photos"}
                     PUT    /photos/:id(.:format)                         {:action=>"update", :controller=>"photos"}
                     DELETE /photos/:id(.:format)                         {:action=>"destroy", :controller=>"photos"}

以下是将路线更改为match 'upload'时的相关路线:

 photo_comments GET    /photos/:photo_id/comments(.:format)          {:action=>"index", :controller=>"comments"}
                     POST   /photos/:photo_id/comments(.:format)          {:action=>"create", :controller=>"comments"}
}
   new_photo_comment GET    /photos/:photo_id/comments/new(.:format)      {:action=>"new", :controller=>"comments"}
  edit_photo_comment GET    /photos/:photo_id/comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"}
       photo_comment GET    /photos/:photo_id/comments/:id(.:format)      {:action=>"show", :controller=>"comments"}
                     PUT    /photos/:photo_id/comments/:id(.:format)      {:action=>"update", :controller=>"comments"}
                     DELETE /photos/:photo_id/comments/:id(.:format)      {:action=>"destroy", :controller=>"comments"}
update_states_photos GET    /photos/update_states(.:format)               {:action=>"update_states", :controller=>"photos"}
        upload_photo        /photos/:id/upload(.:format)                  {:action=>"upload", :controller=>"photos"}
              photos GET    /photos(.:format)                             {:action=>"index", :controller=>"photos"}
                     POST   /photos(.:format)                             {:action=>"create", :controller=>"photos"}
           new_photo GET    /photos/new(.:format)                         {:action=>"new", :controller=>"photos"}
          edit_photo GET    /photos/:id/edit(.:format)                    {:action=>"edit", :controller=>"photos"}
               photo GET    /photos/:id(.:format)                         {:action=>"show", :controller=>"photos"}
                     PUT    /photos/:id(.:format)                         {:action=>"update", :controller=>"photos"}
                     DELETE /photos/:id(.:format)                         {:action=>"destroy", :controller=>"photos"}

不幸的是'匹配'没有更好的效果......

- 编辑 -

这里只是为了确认另一种情况......在路线中:

resources :photos do
    resources :comments
    collection do
        get 'update_states'
    end
    member do
        match 'upload'
    end
end

并在视图中显示:

form_for @photo, :remote => true, :url => { :action => 'upload' }, :html => { :multipart => :true, :id => 'photo_upload' } do |f|

我仍然得到:

No route matches {:action=>"upload", :controller=>"photos"}

3 个答案:

答案 0 :(得分:27)

如果你只是:url => upload_photo_path(@photo)怎么办?

虽然你上传给会员似乎有点奇怪。这只是一种创建方法(在这种情况下你应该只发布到收集路径)?

答案 1 :(得分:2)

我遇到了同样的问题,最终找到了一个我不确定在上述情况下达成的解决方案,因为原来的海报转向了另一种方法。

我的路线

resources :members  do
  member do
    get "invite" 
    post 'register'
  end
end

包括“rake routes”

register_member POST   /members/:id/register(.:format)    {:protocol=>"http", :action=>"register", :controller=>"members"}

然而我一直收到错误

Started POST "/members/149/register" for 127.0.0.1 at 2012-04-13 13:18:35 -0700

ActionController::RoutingError (No route matches "/members/149/register"):

Rendered /Users/lisa/.rvm/gems/ruby-1.9.2-p180@stv/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms)

并且问题仅限于Rails根据以下form_for生成的表单(注意我使用HTTP客户端确认了这一点,手动POST到URL并看到它正在查找路由)

<%= form_for @account, :url => register_member_path(@account.id) do |account_form| %>
   ... 
我检查了方法,检查了路径,一切都很好看。我最终注意到的是,逐行搜索生成的表格:

<form accept-charset="UTF-8" action="/members/149/register" class="edit_member" id="edit_member_149" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="_method" type="hidden" value="put" />
    <input name="authenticity_token" type="hidden" value="74pkMgRHfdowSfzjJGMILkAsivVNrJZ0iWYXRUgxyF0=" />
  </div>
...

注意隐藏的输入名称=“_方法”。我希望Rails将这个解释为PUT已经出现在日志中,这会使我的调试速度更快。我通过明确告诉表单使用POST方法来修复它,当然它已经是,但告诉它删除了隐藏的_method覆盖。我假设@account有一些方面触发Rails使用_method参数,但@account应该是现有记录。

答案 2 :(得分:1)

您的url参数应为

:url =&gt; {:action =&gt; “上传”}


(原始回复)

我敢打赌,因为您的路线需要PUT而且您的表单正在发送POST(可能是因为@photo = Photo.new)。您有几种选择:

  1. 将您的路线更改为post 'upload'
  2. 使用form_for @photo, :as => :post创建包含其余参数的表单
  3. 确保@photo是现有记录(例如,通过致电create代替new
  4. 最合适的选择可能是前两个选择之一。