Рельсы 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"}
... это особенно расстраивает, потому что "фото/: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"}
К сожалению, "матч" не сработал лучше...
-- EDIT --
Просто чтобы подтвердить здесь другой сценарий... с этим в маршрутах:
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 ответа:
Что, если вы просто
:url => upload_photo_path(@photo)
?Хотя мне кажется немного странным, что вы загружаете данные в свой аккаунт. Это просто метод создания (в этом случае вы должны просто опубликовать путь к коллекции)?
У меня была та же проблема, и в конце концов я нашел решение, которое, я не уверен, было достигнуто в вышеупомянутом случае, так как оригинальный плакат перешел к другому подходу.
Мои маршруты имели
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-клиента, чтобы вручную опубликовать 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="✓" /> <input name="_method" type="hidden" value="put" /> <input name="authenticity_token" type="hidden" value="74pkMgRHfdowSfzjJGMILkAsivVNrJZ0iWYXRUgxyF0=" /> </div> ...
Обратите внимание на скрытое имя ввода= "_method". Я хотел бы, чтобы тот факт, что Rails интерпретировал это как PUT, появился в журналах, что сделало бы мою отладку намного быстрее. Я исправил это, сказав форме явно использовать метод POST, который, конечно, уже был, но сказав ему, что удалил скрытый _метод переопределения. Я предполагаю, что есть какой-то аспект @account, который вызвал Rails для использования параметра _method, но @account должен быть существующей записью.
Ваш параметр
url
должен быть: url = > {: action = > "upload"}
(первоначальный ответ)
Я бы поспорил, что это потому, что ваш маршрут ожидаетPUT
, а ваша форма посылаетPOST
(вероятно, потому, что@photo = Photo.new
). У вас есть несколько вариантов:
- измените маршрут на
post 'upload'
- создайте свою форму с
form_for @photo, :as => :post
с остальными аргументами- убедитесь, что
@photo
является существующей записью (например, вызываяcreate
вместоnew
)Наиболее подходящим выбором, вероятно, является один из первых 2.