2011-09-08 10 views
12

Voglio rilevare l'errore di azione sconosciuto in Rails 3, che mostra l'errore "Sconosciuto" sullo sviluppo e il 404.html sulla produzione. Ho provato a mettere questo gestore rescue_from sul mio ApplicationController (e anche su un controller vero e proprio, nel caso) ma continuo a vedere il brutto errore.Catch Azione sconosciuta in Rails 3 per custom 404

Ho roba personalizzata sul 404 e non può essere un semplice file .html.

il mio percorso:

match '/user/:id/:action', controller: 'users' 

L'URL che sto accedendo: /user/elado/xxx

Il codice rescue_from:

rescue_from AbstractController::ActionNotFound, :with => :action_not_found 

def action_not_found 
    render text: "action_not_found" 
end 

L'errore nel browser:

Unknown action 

The action 'xxx' could not be found for UsersController 

E nella console:

Started GET "/user/elado/xxx" for 127.0.0.1 at 2011-09-07 19:16:27 -0700 

AbstractController::ActionNotFound (The action 'xxx' could not be found for UsersController): 

Provato anche rescue_from ActionController::UnknownAction.

Qualche suggerimento? Grazie!

risposta

14

rescue_from era leggermente rotto quando Rails 3 è venuto fuori (ancora rotto in 3.1 troppo). Fondamentalmente non è possibile:

rescue_from ActionController::RoutingError 

più. Vedi here.

La soluzione, per ora, è ciò che hamiltop consiglia. Usa un catch di tutto il percorso che va al tuo percorso di "routing error". Assicurati di metterlo alla fine del tuo file config \ routes.rb in modo che venga elaborato per ultimo.

# Any routes that aren't defined above here go to the 404 
match "*a", :to => "application#routing_error" 

def routing_error 
    render "404", :status => 404 
end 

Nota: Questo metodo presenta un grave inconveniente. Se utilizzi un motore come Jammit o Devise, il percorso di catch all farà in modo che Rails ignori le rotte del motore.

Se non si utilizza un motore con percorsi personalizzati, è necessario procedere. Tuttavia, se si utilizza un motore che definisce i propri percorsi, vedere la risposta di @ arikfr.

+0

Il seguente collegamento fornisce alcune informazioni utili, inoltre fornisce un esempio di come gestire meglio l'eccezione (3.2 o successiva). http://geekmonkey.org/articles/29-exception-applications-in-rails-3-2 – Agustin

0

Hai provato a prendere tutto il percorso?

http://railscasts.com/episodes/46-catch-all-route

Il percorso jolly che siete corrente utilizzando è una cattiva idea (tm).

Vorrei raccomandare di definire i percorsi che ti interessano, e quindi fare un catchall come ultima linea di routes.rb (percorsi definiti prima in routes.rb trump definizioni successive). Quindi puoi eseguire il rendering della pagina desiderata (e specificare il codice di stato 404).

Edit: Se davvero si vuole utilizzare il vostro approccio attuale ... (anche se questo sembra che potrebbe essere deprecato)

def rescue_action (eccezione) caso eccezione quando ActionNotFound, UnknownAction poi # gestire queste eccezioni qui altro Super fine fine

+0

In realtà sto utilizzando il comando catch all route per qualcos'altro, ma in realtà è possibile aggiungere solo l'azione effettiva disponibile anziché: action. Grazie. Ma sto facendo qualcosa di sbagliato con 'rescue_from'? Sembra che dovrebbe funzionare ... – elado

+0

Grazie, comunque 'def rescue_action (eccezione); eccezione caso; quando ActionController :: UnknownAction, AbstractController :: ActionNotFound quindi esegue il rendering del testo: "404"; else render text: "altra eccezione"; fine; end' in ApplicationController o UsersController non ha funzionato. – elado

9

Utilizzando un percorso di cattura tutto per gestire 404 errori (come suggerito da @Seth Jackson) ha uno svantaggio principale: se si utilizzano motori Rails che definiscono i propri percorsi (come Jammit) i loro percorsi verranno ignorati.

Una soluzione migliore e più conforme sarebbe utilizzare un middleware Rack in grado di rilevare errori 404. In uno dei miei progetti, ho implementato tale middleware Rack che riporta questi errori a Hoptoad. Ho basato la mia implementazione su questo: https://github.com/vidibus/vidibus-routing_error, ma invece di richiamare di nuovo la mia app Rails per gestire l'errore 404, lo faccio nel middleware Rack e lascia che nginx mostri la pagina 404.

+0

Bella presa. Mi ero dimenticato di questo. Ho notato questo anche con altri motori (Devise). Aggiungerò una nota a riguardo alla mia risposta. –

1

Se davvero si vuole salvare AbstractController::ActionNotFound in un controllore, si può provare qualcosa di simile:

class UsersController < ApplicationController 

    private 

    def process(action, *args) 
    super 
    rescue AbstractController::ActionNotFound 
    respond_to do |format| 
     format.html { render :404, status: :not_found } 
     format.all { render nothing: true, status: :not_found } 
    end 
    end 


    public 

    # actions must not be private 

end 

Questo ridefinisce il metodo di AbstractController::Baseprocess che alza AbstractController::ActionNotFound (vedi source).