控制器中http引发错误的rails约定?

时间:2013-01-30 05:53:30

标签: ruby-on-rails http model-view-controller exception-handling

假设我有一个带有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也做了类似的事情,如果一个用户没有被授权做某事,它就会引发你自己应该捕获的异常。

1 个答案:

答案 0 :(得分: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