【问题标题】:Double Render Error with simple controller使用简单控制器的双重渲染错误
【发布时间】:2018-12-03 20:31:45
【问题描述】:

我在我的 api rails 应用程序中遇到了一个奇怪的错误:

AbstractController::DoubleRenderError in Api::V1::AdsController#restaurant
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".

我发现这个页面https://api.rubyonrails.org/classes/ActionController/Base.html 是关于双重渲染的,但我真的不明白它们的意思以及它如何适用于我的情况。

我的控制器中有这个:

class Api::V1::AdsController < Api::V1::BaseController
  before_action :set_ad, only: [ :show ]

  def index
    @ads = policy_scope(Subcategory.find_by(nombre: "Restaurantes").ads)
  end

  def restaurant
    @restaurants = policy_scope(Subcategory.find_by(nombre: "Restaurantes").ads)
  end

  def show
  end

  private

  def set_ad
    @ad = Ad.find(params[:id])
    authorize @ad
  end
end

这在我的路线中:

Rails.application.routes.draw do
  devise_for :users
  namespace :api, defaults: { format: :json } do
    namespace :v1 do
      resources :ads, only: [ :index, :show ] do
        collection do
          get 'restaurant', to: 'ads#restaurant'
        end
      end
    end
  end
  root to: 'pages#home'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

我有 3 个视图: index.json.jbuilder:

json.array! @ads do |ad|
  json.extract! ad,
  :id,
  :empresa,
  :direccion_principal,
  :tel,
  :email_principal,
  :web,
  :facebook,
  :instagram,
  :twitter,
  :isla
end

restaurant.json.jbuilder = 同索引

show.json.jbuilder:

json.extract! @ad, :id, :empresa, :direccion_principal

有人能看出这里的问题吗?

编辑:

广告政策:

class AdPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all
    end
  end

  def show?
    true
  end
end

基础控制器:

class Api::V1::BaseController < ActionController::API
  include Pundit

  after_action :verify_authorized, except: :index
  after_action :verify_policy_scoped, only: :index

  rescue_from StandardError,                with: :internal_server_error
  rescue_from Pundit::NotAuthorizedError,   with: :user_not_authorized
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  private

  def user_not_authorized(exception)
    render json: {
      error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
    }, status: :unauthorized
  end

  def not_found(exception)
    render json: { error: exception.message }, status: :not_found
  end

  def internal_server_error(exception)
    if Rails.env.development?
      response = { type: exception.class.to_s, message: exception.message, backtrace: exception.backtrace }
    else
      response = { error: "Internal Server Error" }
    end
    render json: response, status: :internal_server_error
  end
end

【问题讨论】:

  • 可以添加policy_scope方法的内容吗?你的BaseController 中有before_actions 吗?
  • @GavinMiller 我添加了你提到的两件事。

标签: ruby-on-rails json api activerecord render


【解决方案1】:

我找到了自己问题的答案。它与 BaseController 有关。我忘记在 after_action :verify_authorized 和 verify_policy_scoped 中添加 :restaurant。有了下面的 BaseController,它现在可以工作了。

class Api::V1::BaseController < ActionController::API
  include Pundit

  after_action :verify_authorized, except: [:index, :restaurant]
  after_action :verify_policy_scoped, only: [:index, :restaurant, :beach_restaurant, :cafe]

  rescue_from StandardError,                with: :internal_server_error
  rescue_from Pundit::NotAuthorizedError,   with: :user_not_authorized
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  private

  def user_not_authorized(exception)
    render json: {
      error: "Unauthorized #{exception.policy.class.to_s.underscore.camelize}.#{exception.query}"
    }, status: :unauthorized
  end

  def not_found(exception)
    render json: { error: exception.message }, status: :not_found
  end

  def internal_server_error(exception)
    if Rails.env.development?
      response = { type: exception.class.to_s, message: exception.message, backtrace: exception.backtrace }
    else
      response = { error: "Internal Server Error" }
    end
    render json: response, status: :internal_server_error
  end
end

【讨论】:

    猜你喜欢
    • 2018-02-23
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多