Ruby-on-rails 用于自定义操作的 Rails 3 表单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4697176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:06:21  来源:igfitidea点击:

Rails 3 Form For Custom Action

ruby-on-railsformsruby-on-rails-3custom-action

提问by Andrew

I'm having trouble routing a form to a custom action in Rails 3. Here are my routes:

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

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

Here's the form_for:

这是form_for:

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

And here's the error message:

这是错误消息:

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

... this is especially frustrating because "photos/:id/upload" is exactlythe correct action for this form.

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

What am I missing?

我错过了什么?

EDITS - Here are the original Photo-related routes:

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

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

Here are the relevant routes when I changed the route to match 'upload':

以下是我将路线更改为时的相关路线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"}

Unfortunately 'match' didn't work any better...

不幸的是,“匹配”没有更好的效果......

-- EDIT --

- 编辑 -

Just to confirm another scenario here... with this in the routes:

只是为了确认这里的另一个场景......在路线中使用这个:

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

and this in the view:

这在视图中:

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

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

I still get:

我仍然得到:

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

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

回答by davemyron

What if you did just :url => upload_photo_path(@photo)?

如果你只是这样做:url => upload_photo_path(@photo)呢?

It seems a little strange that you'd be uploading to a member though. Is this just a creation method (in which case you should just POST to the collection path)?

不过,您要上传给会员似乎有点奇怪。这只是一种创建方法吗(在这种情况下,您应该只 POST 到集合路径)?

回答by LisaD

I had the same problem and finally worked through to a solution which I'm not sure was reached in the above case, since the original poster moved on to another approach.

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

My routes had

我的路线有

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

And "rake routes" included

和“耙路线”包括

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

Yet I kept getting the error

但我一直收到错误

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)

and the problem was limited only to the form generated by Rails according to the below form_for (note I confirmed this using HTTP client to manually POST to the URL and saw it was finding the route)

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

<%= form_for @account, :url => register_member_path(@account.id) do |account_form| %>
   ... 

I checked the method, I checked the path, everything looked good. What I finally noticed, scouring the generated form line by line:

我检查了方法,我检查了路径,一切看起来都很好。我终于注意到了,逐行搜索生成的表单:

<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>
...

Notice the hidden input name="_method". I wish the fact that Rails was interpreting this as a PUT had shown up in the logs, that would have made my debugging a lot faster. I fixed it by telling the form explicitly to use the POST method, which of course it was already, but telling it that removed the hidden _method override. I assume there's some facet about @account which triggered Rails to use the _method parameter, but @account should be an existing record.

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

回答by David Sulc

Your urlparameter should be

你的url参数应该是

:url => { :action => "upload" }

:url => { :action => "上传" }



(Original reply)

(原回复)

I would bet it's because your route expects a PUTand your form is sending a POST(probably because @photo = Photo.new). You have several options:

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

  1. Change your route to post 'upload'
  2. Create your form with form_for @photo, :as => :postwith the rest of your arguments
  3. Make sure @photois an existing record (e.g. by calling createinstead of new)
  1. 将您的路线更改为 post 'upload'
  2. form_for @photo, :as => :post使用其余参数创建表单
  3. 确保@photo是现有记录(例如通过调用create而不是new

The most appropriate choice is probably one of the first 2.

最合适的选择可能是前两个之一。