2016-05-18 27 views
1

我的Rails 4應用程序使用RocketPants爲其JSON API和權威授權。如何在Rails rescue_from語句中重新引發Ruby異常?

我有我的/app/controllers/api/v1/base_controller.rb文件中的代碼來處理來自Pundit的錯誤。每當用戶無權更新資源,權威人士拋出一個異常NotAuthorizedError,我與我的user_not_authorized方法挽救:

class API::V1::BaseController < RocketPants::Base 
    include Pundit 
    version 1 

    rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized 

    def user_not_authorized 
    error! :forbidden 
    end 

end 

當我致電error!方法RocketPants provides從我的異常處理程序,我期望能獲得這樣的JSON響應:

{ 
    "error":    "forbidden", 
    "error_description": "The requested action was forbidden." 
} 

相反,但是,調用error!只是立即炸燬要求:

Completed 500 Internal Server Error in 143ms 

RocketPants::Forbidden - RocketPants::Forbidden: 
    rocket_pants (1.13.1) lib/rocket_pants/controller/error_handling.rb:44:in `error!' 
    app/controllers/api/v1/base_controller.rb:61:in `user_not_authorized' 

滿堆棧跟蹤here

爲什麼error!方法在我的Pundit異常處理程序中調用時應該如何執行?

如果我把error! :forbidden置於我的控制器操作的中間,它按預期工作。

爲背景,從base_controller.rb繼承和調用權威人士的authorize方法控制器看起來是這樣的:

class API::V1::MealsController < API::V1::BaseController 

    before_filter :find_entity 

    def create 
    meal = @entity.meals.build(meal_params) 

    authorize(@entity, :update?) 

    if meal.save 
     expose meal, status: :created 
    else 
     expose meal.errors, status: 422 
    end 
    end 

end 

回答

0

rescue_from顯然引發異常是一個壞主意,並根據Rails的文檔,在一個引起的異常處理程序不冒泡:

在異常處理程序內引發的異常不會傳播出去。

文檔:http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html

而不是重新提高RocketPants'例外,我只是創建並返回的JSON錯誤信息自己:

def user_not_authorized 
    # error! :forbidden 
    head 403 
    error = { error: 'Action not allowed.', error_description: 'Sorry, you are not allowed to perform this action.'} 
    expose error 
    end 

這工作!

UPDATE

我因爲找到了一個更好的解決方法:只地圖的權威人士例外RocketPants例外。這意味着無論何時出現Pundit::NotAuthorizedError錯誤,都會將其視爲RocketPants::Forbidden錯誤。

拿到的base_controller.rb頂部的整個解決方案到一個單一的代碼行:

map_error! Pundit::NotAuthorizedError, RocketPants::Forbidden 

無需處理。