Rails 3 Форма для пользовательских действий - PullRequest
15 голосов
/ 15 января 2011

У меня проблемы с маршрутизацией формы к пользовательскому действию в 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 ]

27 голосов
/ 15 января 2011

Что, если вы сделали просто :url => upload_photo_path(@photo)?

Кажется немного странным, что вы загружаете пользователя. Это просто метод создания (в этом случае вы должны просто отправить POST к пути сбора)?

2 голосов
/ 14 апреля 2012

У меня возникла та же проблема, и я, наконец, нашел решение, которое, я не уверен, было достигнуто в приведенном выше случае, поскольку исходный плакат перешел к другому подходу.

В моих маршрутах было

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)

, и проблема была ограничена только формой, сгенерированной 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>
...

Обратите внимание на скрытый ввод name = "_ method".Мне бы хотелось, чтобы тот факт, что Rails интерпретировал это как PUT, был обнаружен в журналах, что сделало бы мою отладку намного быстрее.Я исправил это, явно указав форме использовать метод POST, что, конечно, уже было, но сообщив, что убрал скрытое переопределение _method.Я предполагаю, что в @account есть некоторый аспект, который заставил Rails использовать параметр _method, но @account должен быть существующей записью.

1 голос
/ 15 января 2011

Ваш url параметр должен быть

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


(Оригинальный ответ)

Я быСпорим, это потому, что ваш маршрут ожидает PUT, а ваша форма отправляет POST (вероятно, потому что @photo = Photo.new).У вас есть несколько вариантов:

  1. Измените свой маршрут на post 'upload'
  2. Создайте форму с помощью form_for @photo, :as => :post с остальными аргументами
  3. Убедитесь, @photo является существующей записью (например, путем вызова create вместо new)

Наиболее подходящим выбором, вероятно, является один из первых 2.

...