0

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 も同様のことを行います。ユーザーが何かを行う権限がない場合、キャッチする必要がある独自の例外が発生します。

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 に答える