如何使用 AJAX JSON 响应来响应 CanCan::AccessDenied?

How do I respond to CanCan::AccessDenied with an AJAX JSON response?

如果请求是通过 AJAX,我想用 JSON 响应 CanCan::AccessDenied,但无论如何它总是以状态 200 和重定向响应。我想实现这个答案:。我不知道它是如何将状态 302 覆盖到 200 的,更不用说不渲染 JSON。我也试过 format.js 但没用。

application_controller.rb
class ApplicationController < ActionController::Base
  include CanCan::ControllerAdditions

  rescue_from CanCan::AccessDenied do |exception|
    flash[:warning] = exception.message
    logger.info exception
    respond_to do |format|
      logger.info "format: " + format.to_s
      format.html do
        if user_signed_in? && current_user.type
          redirect_to "/dashboard"
        else
          redirect_to root_path
        end
      end
      format.json do
        render json: {success: false, message: 'Access Denied: '+exception.message}, status: 401
      end
    end
  end
CoffeeScript
$.post "/topics/order", {'id_order[]': arr}, (data, textStatus, jqXHR) ->
  ...
Gemfile
gem 'cancancan', '~> 1.10'
Console
Started POST "/topics/order" for ::1 at 2018-09-14 14:44:33 -0400
...
You are not authorized to access this page.
format: #<ActionController::MimeResponds::Collector:0x0000000d4b2a28>
Redirected to http://localhost:3000/dashboard
Completed 200 OK in 314ms (ActiveRecord: 28.0ms)

https://github.com/CanCanCommunity/cancancan#4-handle-unauthorized-access

https://api.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_to


我做了一些测试并添加了

  format.json { head :forbidden, content_type: 'text/html' }
  format.js   { head :forbidden, content_type: 'text/html' }

respond_to 块的顶部,它确实有效。当移动到块的底部时,它不起作用。 Rails 似乎在响应它看到的第一个 format,无论格式如何!

我将 json 作为 dataType 添加到 post,现在可以使用了。

$.post "/topics/order", {'id_order[]': arr}, (data, textStatus, jqXHR) ->
  ...
, 'json'

https://api.jquery.com/jquery.ajax/#jQuery-ajax-settings

dataType (default: Intelligent Guess (xml, json, script, or html))
Type: String
The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string). The available types (and the result passed as the first argument to your success callback) are:

"json": Evaluates the response as JSON and returns a JavaScript object. Cross-domain "json" requests that have a callback placeholder, e.g. ?callback=?, are performed using JSONP unless the request includes jsonp: false in its request options. The JSON data is parsed in a strict manner; any malformed JSON is rejected and a parse error is thrown. As of jQuery 1.9, an empty response is also rejected; the server should return a response of null or {} instead. (See json.org for more information on proper JSON formatting.)