2011-09-08 4 views
12

Tôi muốn phát hiện lỗi hành động không xác định trong Rails 3, hiển thị lỗi "Hành động không xác định" khi phát triển và 404.html về sản xuất. Tôi đã thử đặt xử lý này rescue_from trên ApplicationController của tôi (và cũng trên một bộ điều khiển thực tế, chỉ trong trường hợp) nhưng tôi vẫn thấy lỗi xấu xí.Bắt hành động không xác định trong Rails 3 cho tuỳ chỉnh 404

Tôi có nội dung tùy chỉnh trên 404 và không thể là tệp .html đơn giản.

tuyến đường của tôi:

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

URL Tôi đang truy cập: /user/elado/xxx

Các rescue_from mã:

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

def action_not_found 
    render text: "action_not_found" 
end 

Các lỗi trong trình duyệt:

Unknown action 

The action 'xxx' could not be found for UsersController 

Và trong giao diện điều khiển:

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

cũng rescue_from ActionController::UnknownAction thử.

Mọi đề xuất? Cảm ơn!

Trả lời

14

rescue_from được hơi bị hỏng khi Rails 3 ra (vẫn còn bị phá vỡ trong 3,1 quá). Về cơ bản, bạn không thể:

rescue_from ActionController::RoutingError 

nữa. Xem here.

Giải pháp, hiện tại là những gì hamiltop đề xuất. Sử dụng tuyến đường bắt tất cả tuyến đường "lỗi định tuyến" của bạn. Hãy chắc chắn rằng bạn đặt nó ở cuối tập tin config \ routes.rb của bạn để nó được xử lý cuối cùng.

# 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 

Lưu ý: Phương pháp này có một nhược điểm lớn. Nếu bạn sử dụng một công cụ như Jammit hoặc Devise, tất cả các tuyến đường sẽ làm cho Rails bỏ qua các tuyến đường của động cơ.

Nếu bạn không sử dụng động cơ có lộ trình riêng thì bạn sẽ ổn. Tuy nhiên, nếu bạn sử dụng một công cụ xác định các tuyến đường riêng của mình, hãy xem câu trả lời của @ arikfr.

+0

Liên kết sau đây cung cấp một số thông tin chi tiết tốt, nó cũng đưa ra một ví dụ về cách xử lý ngoại lệ tốt hơn (3.2 hoặc cao hơn). http://geekmonkey.org/articles/29-exception-applications-in-rails-3-2 – Agustin

0

Bạn đã thử bắt tất cả tuyến đường chưa?

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

Tuyến ký tự đại diện mà bạn đang hiện hành sử dụng là một ý tưởng tồi (tm).

Tôi khuyên bạn nên xác định các tuyến đường mà bạn quan tâm và sau đó thực hiện catchall làm tuyến cuối cùng.rb (tuyến đường được định nghĩa đầu tiên trong các tuyến đường.rb trump later definitions). Sau đó, bạn có thể hiển thị bất kỳ trang nào bạn muốn (và chỉ định mã trạng thái 404).

Edit: Nếu bạn thực sự muốn sử dụng cách tiếp cận hiện tại của bạn ... (mặc dù điều này có vẻ như nó có thể được tán thành)

def rescue_action (ngoại lệ) trường hợp ngoại lệ khi ActionNotFound, UnknownAction sau đó # Xử lý những trường hợp ngoại lệ ở đây khác siêu cuối cuối

+0

Tôi thực sự sử dụng bắt tất cả tuyến đường cho một thứ khác, nhưng tôi thực sự chỉ có thể thêm hành động có sẵn thực tế thay vì: hành động. Cảm ơn. Nhưng tôi có làm gì sai với 'rescue_from'? Có vẻ như nó sẽ hoạt động ... – elado

+0

Cảm ơn, mặc dù 'def rescue_action (ngoại lệ); trường hợp ngoại lệ; khi ActionController :: UnknownAction, AbstractController :: ActionNotFound sau đó hiển thị văn bản: "404"; khác làm cho văn bản: "ngoại lệ khác"; kết thúc; end' trong ApplicationController hoặc UsersController không hoạt động. – elado

9

Sử dụng bắt tất cả tuyến đường để xử lý lỗi 404 (như @ Jackson gợi ý) có một nhược điểm chính: nếu bạn sử dụng bất kỳ công cụ Rails nào xác định tuyến đường của riêng mình (chẳng hạn như Jammit), tuyến đường của họ sẽ bị bỏ qua.

Giải pháp tốt hơn và phù hợp hơn là sử dụng phần mềm trung gian Rack sẽ phát hiện lỗi 404. Trong một trong các dự án của tôi, tôi đã triển khai phần mềm trung gian Rack như vậy để báo cáo các lỗi này cho Hoptoad. Tôi đã dựa trên việc triển khai thực hiện của tôi trên cái này: https://github.com/vidibus/vidibus-routing_error, nhưng thay vì gọi lại ứng dụng Rails của tôi một lần nữa để xử lý lỗi 404, tôi làm điều đó trong phần mềm trung gian Rack và để nginx hiển thị trang 404.

+0

Rất thú vị. Tôi đã quên mất điều này. Tôi đã nhận thấy điều này với các động cơ khác (Devise). Tôi sẽ thêm một lưu ý về điều này vào câu trả lời của tôi. –

1

Nếu bạn thực sự muốn cứu AbstractController::ActionNotFound trong một bộ điều khiển, bạn có thể thử một cái gì đó như thế này:

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 

này ghi đè phương pháp process của AbstractController::Base làm tăng AbstractController::ActionNotFound (xem source).