2011-09-08 17 views
12

Rails 3で未知のアクションエラーが発生しました。これは開発上の "不明なアクション"エラーとプロダクションでの404.htmlを示しています。私はこのrescue_fromハンドラを私のApplicationController(と実際のコントローラの場合)に入れてみましたが、まだ醜いエラーが表示されます。Rails 3でカスタム404の不明なアクションをキャッチ

私は404にカスタムのものを持っていますし、プレーンな.htmlファイルにすることはできません。

マイルート:

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

URL私がアクセスしています:/user/elado/xxx

rescue_fromコード:

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

def action_not_found 
    render text: "action_not_found" 
end 

ブラウザでのエラー:

Unknown action 

The action 'xxx' could not be found for UsersController 

とコンソールに:

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): 

rescue_from ActionController::UnknownActionしようとしました。

提案がありますか? ありがとう!

答えて

14

rescue_fromは、わずかに(まだあまりにも3.1に壊れて)壊れていました。基本的に次のことはできません。

rescue_from ActionController::RoutingError 

hereを参照してください。

解決策は、今のところ、hamiltopが推奨するものです。あなたの "ルーティングエラー"ルートに行くキャッチオールルートを使用してください。 config \ routes.rbファイルの末尾に置いて、最後に処理されるようにしてください。

# 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 

注:この方法は、一つの大きな欠点があります。あなたがJammitやDeviseのようなエンジンを使用している場合、catchのすべてがルーティングされるため、Railsはエンジンのルートを無視します。

独自のルートを持つエンジンを使用していない場合は、正常に動作するはずです。 しかし、独自のルートを定義するエンジンを使用すると、@ arikfrの答えが表示されます。

+0

次のリンクは、良い見識を示しています。また、例外(3.2以上)の処理方法の例も示しています。 http://geekmonkey.org/articles/29-exception-applications-in-rails-3-2 – Agustin

0

キャッチオールルートを試しましたか?あなたが使用して現在ある

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

ワイルドカードのルートは悪いアイデア(TM)です。

あなたが気にするルートを定義し、次にroutes.rbの最後の行としてcatchallを実行することをお勧めします(routes.rb trump laterの定義で最初に定義されたルート)。次に、任意のページをレンダリングすることができます(404ステータスコードを指定します)。

編集:(これは、それが廃止される可能性のように思えるが)あなたが本当に...あなたの現在のアプローチを使用したい場合は

デフrescue_action(例外) 場合は例外 ActionNotFound、UnknownActionは、 #は、これらを取り扱う際Railsの3が出てきたとき、ここでの例外は 他 スーパー エンド エンド

+0

私は実際には他の何かのためにすべての経路をキャッチしていますが、私は実際にアクションの代わりに実際に利用可能なアクションだけを追加できます。ありがとう。しかし、私は 'rescue_from'で何か間違っているのですか?それは動作する必要があるように見えます... – elado

+0

おかげで、 'def rescue_action(exception);ケースの例外。 ActionController :: UnknownAction、AbstractController :: ActionNotFoundのときにテキストをレンダリングする: "404"; else text: "その他の例外";終わり; ApplicationControllerまたはUsersControllerの「end」は機能しませんでした。 – elado

9

(@Seth Jacksonが示唆しているように)404エラーを処理するcatch all routeを使うと、1つの大きな欠点があります。自分のルート(Jammitなど)を定義するRailsエンジンを使用すると、

さらに改善された解決策は、404エラーを捕捉するラックミドルウェアを使用することです。私のプロジェクトの1つでは、Hoptoadにこれらのエラーを報告するRackミドルウェアを実装しました。私はこの実装に基づいて実装しました:https://github.com/vidibus/vidibus-routing_errorが、私のRailsアプリケーションを再度呼び出して404エラーを処理するのではなく、Rackミドルウェアで実行し、nginxに404ページを表示させます。

+0

ニースキャッチ。私はこれを忘れていた。私は他のエンジン(Devise)でもこれに気付いています。私はこれについて私の答えに書き留めておきます。 –

1

あなたが本当にコントローラでAbstractController::ActionNotFoundを救出したい場合は、このような何か試すことができます。

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 

これはAbstractController::ActionNotFoundを提起AbstractController::Baseprocessメソッドをオーバーライドする(sourceを参照してください)。

関連する問題