0

假设我有一个带有 show 方法的articles_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

但这会导致双重渲染错误,所以现在我将尝试不同的东西

# 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 状态,而且我还捕获了我可能不想捕获的路由错误。

做我想做的事情的正确方法是什么?

我所描述的行为就是设计所做的。如果您向具有 authorize_user 的操作发出请求!例如,它会引发错误,并将用户重定向到某个页面。CanCan 也做了类似的事情,如果用户没有被授权做某事,它会引发你应该捕获的自己的异常。

4

1 回答 1

0

错误是有效的,你渲染了不止一次,这就是doublerender异常的原因。最好只在控制器中进行渲染

试试这个代码

def show
  is_client_valid = authenticate_license if params[:format] == 'json' 
  # boilerplate
  respond_to do |format|
    format.html
    if is_client_valid == 'valid' #you can have a switch statement here, so that you can easily set the status tag
      format.json { render json: @article, status: :ok }
    else
       format.json { render json: is_client_valid }
    end
  end
end


# in application_controller
def authenticate_license
  @client = params[:client]
  licenses = License.where(:code => params[:code])
  @license = licenses.first
  if @license
    if @license.client = @client
      return 'valid'
    else
        return 'wrong client' 
    end
  else
      return 'bad licence'
  end
end
于 2013-01-30T06:07:32.213 回答