我的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
有人可以在这里看到问题吗?
编辑:
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
答案 0 :(得分:0)
我找到了自己问题的答案。它与BaseController有关。我忘记将:restaurant添加到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