show メソッドを含む article_controller があるとしましょう
有効なライセンス コードを持つクライアントのみが、このコントローラー アクションの json エンドポイントを読み取れるようにしたい
def show
authenticate_license if params[:format] == 'json'
# boilerplate
respond_to do |format|
format.html
format.json { render json: @article, status: :ok }
end
end
この認証ブロックを別の場所で使用したいかもしれないので、application_controller に入れます。
# in application_controller
def authenticate_license
@client = params[:client]
licenses = License.where(:code => params[:code])
@license = licenses.first
if @license
if @license.client = @client
# do nothing, we're fine
else
respond_to do |format|
format.json { render json: 'wrong client', status: 400 }
end
end
else
respond_to do |format|
format.json { render json: 'bad license', status: :forbidden }
end
end
end
しかし、これにより doublerendererror が発生するため、別のことを試してみます
# in application_controller
def authenticate_license
licenses = License.where(:code => params[:code]
@license = licenses.first
if @license
if @license.client = @client
# do nothing, we're fine
else
raise ActionController::RoutingError.new('wrong client')
end
else
raise ActionController::RoutingError.new('bad license code')
end
end
rescue_from ActionController::RoutingError do |exception|
respond_to do |format|
format.html { redirect_to root_url, :alert => exception.message }
format.json { render json: exception.message, status: :forbidden }
end
end
しかし、この方法では、HTTP ステータスを指定することはできず、おそらくキャッチしたくないルーティング エラーもキャッチされます。
私がやりたいことをする正しい方法は何ですか?
私が説明している動作は、devise が行うことのようなものです。authorize_user! を持つアクションにリクエストを行うと、たとえば、メソッドはエラーを発生させ、ユーザーを何らかのページにリダイレクトします。CanCan も同様のことを行います。ユーザーが何かを行う権限がない場合、キャッチする必要がある独自の例外が発生します。