web-dev-qa-db-ja.com

Rails 3カスタムアクションのフォーム

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

15
Andrew

:url => upload_photo_path(@photo)だけを実行した場合はどうなりますか?

ただし、メンバーにアップロードするのは少し奇妙に思えます。これは単なる作成方法ですか(この場合、コレクションパスにPOST)する必要があります)?

27
davemyron

私は同じ問題を抱えていましたが、元のポスターが別のアプローチに移行したため、最終的に上記のケースで到達したかどうかわからない解決策に取り組みました。

私のルートは

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

そして「レーキルート」が含まれています

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)

問題は、以下のform_forに従ってRailsによって生成されたフォームのみに限定されていました(HTTPクライアントを使用して手動でこれを確認したことに注意してくださいPOST URLとルートを見つけていたのを見た)

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

メソッドをチェックし、パスをチェックしました。すべてが良さそうです。生成されたフォームを1行ずつ精査して、最終的に気付いたのは次のとおりです。

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

非表示の入力name = "_method"に注意してください。 RailsがこれをPUTがログに表示されたものとして解釈していたため、デバッグが大幅に高速化されたと思います。フォームに=を使用するように明示的に指示することで修正しました。 POSTメソッド、もちろんそれはすでにありましたが、隠された_methodオーバーライドを削除したことを伝えています。使用するRailsをトリガーした@accountに関するいくつかの側面があると思います_methodパラメーターですが、@ accountは既存のレコードである必要があります。

2
LisaD

urlパラメータは次のようになります

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


(元の返信)

ルートがPUTを予期していて、フォームがPOSTを送信しているためだと思います(おそらく@photo = Photo.newのため)。いくつかのオプションがあります。

  1. ルートをpost 'upload'に変更します
  2. form_for @photo, :as => :postと残りの引数を使用してフォームを作成します
  3. @photoが既存のレコードであることを確認します(たとえば、createの代わりにnewを呼び出します)

最も適切な選択は、おそらく最初の2つのうちの1つです。

1
David Sulc