Ошибка двойного рендеринга с простым контроллером - PullRequest
0 голосов
/ 03 декабря 2018

Я получаю странную ошибку в моем приложении 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 = так же, как index

show.json.jbuilder:

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

Может кто-нибудь увидетьпроблема здесь?

РЕДАКТИРОВАТЬ:

AdPolicy:

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

1 Ответ

0 голосов
/ 04 декабря 2018

Я нашел ответ на свой вопрос.Это было связано с BaseController.Я забыл добавить: ресторан к after_action: verify_authorized и verify_policy_scoped.С 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
...