2011-01-15 14 views
15

Ho problemi di routing di un modulo per un'azione personalizzata in Rails 3. Qui sono le mie vie:Rails 3 Modulo di azione personalizzata

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

Ecco il form_for:

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

Ed ecco il messaggio di errore:

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

... questo è particolarmente frustrante perché "foto /: id/upload" è esattamente l'azione corretta per questo modulo.

Cosa mi manca?

EDITS - Ecco le Foto originale legate percorsi:

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

Ecco relative rotte quando ho cambiato il percorso per 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"} 

Purtroppo 'match' non ha funzionato meglio ...

- EDIT -

Solo per confermare un altro scenario qui ... con questo negli itinerari:

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

e questo nella vista:

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

ho ancora ottenere:

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

risposta

27

Cosa succede se hai fatto solo :url => upload_photo_path(@photo)?

Sembra un po 'strano che tu stia caricando su un membro. Si tratta solo di un metodo di creazione (nel qual caso è necessario caricare POST nel percorso di raccolta)?

+0

Potrei provarci più tardi, ma ho deciso di andare in una direzione completamente nuova. Il motivo per il caricamento su un membro è che stavo creando, preparando e salvando quando l'utente fa clic su "nuovo", quindi in realtà stanno modificando il record mentre riempiono le informazioni per la prima volta. L'ho fatto perché voglio essere in grado di salvare i loro progressi mentre vanno, e ci sono diversi modelli associati che hanno bisogno dell'ID genitore per poter salvare correttamente .... comunque, questo era troppo dolore, quindi sto provando per elaborare un nuovo approccio interamente. – Andrew

+1

Beh, solo per quello che sai, se solo non avessi usato il bit '{: action => ...}' - e invece avessi fatto quello che ho suggerito sopra - avresti avuto successo. Quello che stavi dicendo che l'helper della generazione di url per generare era, infatti, che volevi postare su un'azione sul controller che si chiamava l'output di 'upload_photo_path (@photo)' - che ** stesso ** contiene il controller e nomi di azioni (come puoi vedere nell'errore "Nessuna corrispondenza corrisponde ...") – davemyron

+0

Ok, ho fatto un test di questo per essere sicuro, e hai ragione, questo ha creato il percorso come hai detto tu. Non lo userò più allo stesso modo (altri problemi con la mia implementazione), ma questa è una soluzione valida. Grazie :) – Andrew

1

Il parametro url deve essere

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


(risposta originale)

Sono pronto a scommettere che sia perché il percorso si aspetta un PUT e la vostra forma è l'invio di un POST (probabilmente perché @photo = Photo.new). Sono disponibili diverse opzioni:

  1. cambiare strada per post 'upload'
  2. Crea il tuo modulo con form_for @photo, :as => :post con il resto dei vostri argomenti
  3. Assicurarsi @photo è un record esistente (ad esempio chiamando create invece di new)

la scelta più appropriata è probabilmente uno dei primi 2.

+0

Bene, controllando questi: @photo è sicuramente un record esistente. L'argomento: method è impostato su 'put', ma per sicurezza ho provato a cambiare il percorso per postare 'upload' ... nessun dado. Usando: as =>: post non ha risolto il problema, né lo ha fatto: as =>: inserire il percorso impostato su 'put update' – Andrew

+0

Provare a impostare il percorso su 'match' upload''. Inoltre, pubblica l'output di 'rake routes'. –

+0

Non aggiustato ... – Andrew

2

Ho avuto lo stesso problema e alla fine ho lavorato a una soluzione che non sono sicuro sia stata raggiunta nel caso precedente, poiché il poster originale è passato a un altro approccio.

miei itinerari avevano

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

e "rake routes" inclusi

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

Eppure ho continuato a ottenere l'errore

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/[email protected]/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms) 

e il problema è stato limitato solo alla forma generato da Rails in base al seguente form_for (nota che ho confermato questo utilizzando il client HTTP per passare manualmente a t lui URL e vide che stava trovando il percorso)

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

Ho controllato il metodo, ho controllato il percorso, tutto sembrava buono. Quello che ho finalmente notato, perlustrando il modulo generato riga per riga:

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

Notare il nome dell'ingresso nascosto = "metodo". Vorrei che il fatto che Rails interpretasse questo come un PUT si fosse mostrato nei log, avrebbe reso il mio debugging molto più veloce. L'ho risolto dicendo esplicitamente al modulo di usare il metodo POST, che ovviamente era già, ma dicendogli che rimuoveva l'override del _method nascosto. Presumo che ci sia qualche sfaccettatura su @account che ha attivato Rails per usare il parametro _method, ma @account dovrebbe essere un record esistente.

+0

Interessante, potrebbe aver influito anche su di me, ma poiché ho usato 'match' invece di' post' nei miei percorsi avrebbe dovuto funzionare in entrambi i casi nel mio caso. Ottima aggiunta a questa domanda, perché sono sicuro che altri troveranno utile la tua soluzione! – Andrew