【问题标题】:AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action not duplicationAbstractController::DoubleRenderError(在此操作中多次调用渲染和/或重定向,而不是重复
【发布时间】:2020-10-29 00:05:09
【问题描述】:

我知道这个错误 AbstractController::DoubleRenderError(在此操作中多次调用渲染和/或重定向在多次渲染时发生

但已经使用解决方案and return

class FrequentMethodController < ApplicationController
  def post_exist?(post_id)
    post = Post.find_by_id(post_id)
    render_json('post_not found', 400, 'msg') unless post
    return post
  end
  def render_json(data, status_code, main_key = 'data')
    render json: { "#{main_key}": data }, status: status_code and return 
  end
end

class PostController < FrequentMethodController
  def view_post
     post_id = params[:post_id]
     post = post_exist?(post_id)
     # test code 
     render_json(post, 1, 'data')
 end
end

并尝试使用render direct 但不起作用

   render :json => { :msg => 'post not found ' },:status => 400 and return

使用'rails', '5.1.4'

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:
    class FrequentMethodController < ApplicationController
      def post_exist?(post_id)
        post = Post.find_by_id(post_id)
        render_json('post_not found', 400, 'msg') unless post
        return post # <------------------------------------------------------------ THIS
      end
    
      def render_json(data, status_code, main_key = 'data')
        render json: { "#{main_key}": data }, status: status_code and return # <--- AND THIS
      end
    end
    

    Rails 首先在render_json 方法中看到return,当它退出该方法时,它会在post_exists? 中看到另一个返回

    尝试将您的退货移至 render_json 方法之外:

    class FrequentMethodController < ApplicationController
      def post_exist?(post_id)
        post = Post.find_by_id(post_id)
        render_json('post_not found', 400, 'msg') and return unless post
        return post
      end
    
      def render_json(data, status_code, main_key = 'data')
        render json: { "#{main_key}": data }, status: status_code
      end
    end
    

    您还可以使用 if 语句消除 and return

    class FrequentMethodController < ApplicationController
      def post_exist?(post_id)
        post = Post.find_by_id(post_id)
    
        if post
          return post
        else
          render_json('post_not found', 400, 'msg')
          # if this is the only place render_json is used, I wouldn't bother making it a method
          # render json: { 'msg': 'post_not found' }, status: 400
        end
      end
    
      def render_json(data, status_code, main_key = 'data')
        render json: { "#{main_key}": data }, status: status_code
      end
    end
    

    更新:

    当我们从 PostController 开始时,这里实际上有一个 TRIPLE 返回。

    1. Rails 访问PostController#view_post
    2. Rails 转到 FrequentMethodController#post_exists?
    3. 当仍在FrequentMethodController#post_exists? 中时,Rails 转到FrequentMethodController#render_json? 并找到return #1
    4. Rails 返回到 FrequentMethodController#post_exists? 并找到 return #2
    5. Rails 回到 PostController#view_post 并看到 render_json(再次!!)
    6. Rails 转到 FrequentMethodController#post_exists? 并找到 return #3

    这段代码是意大利面条。

    如果FrequentMethodController 真的只是一个帮助文件,那么我认为它应该永远有一个return。将早期returns 保持在最低限度,并且仅在模型的主控制器中。

    提前返回有助于清理复杂和嵌套的 if 语句,并可能使代码更具可读性,但这里没有这个问题。事实上,所有这些返回值都使您的代码变得脆弱、不可预测且过于复杂。

    总的来说,我认为FrequentMethodController 是个坏主意。

    • 我认为post_exist?(post_id) 应该返回真或假。
    • 我认为render_json 足够简单,不应该是它自己的方法。

    而且,你已经hijacked the normal CRUD structure

    我会这样做:

    class PostController < ApplicationController
      before_action :set_post, only: [:show, :edit, :update, :destroy]
    
      # changed name from view_post
      def show
         if @post
           render @post.as_json
         else
           render json: { 'msg': 'post_not found' }, status: 400
         end
      end
    
      private
    
      def set_post
        @post = Post.find(params[:id])
      end
    end
    

    请注意,上述代码没有显式返回,并且不需要手动帮助文件。

    【讨论】:

    • 无法修复与另一个控制器调用时出现的问题PostController &lt; FrequentMethodController
    • 我不明白你的评论。你为什么还要创建FrequentMethodController?只需将ApplicationHelper 用于跨控制器的可重用方法。 PostController 应该直接从 ApplicationController 继承。
    • 我在FrequentMethodController中添加FrequentMethod并继承给其他控制器
    • @TalaatMagdy,查看我的更新。我认为你已经偏离了轨道。我认为坚持路由和控制器的更多标准约定会更轻松。
    【解决方案2】:

    试试这个

    def view_post
      post_id = params[:post_id]
      if post = post_exist?(post_id)
        # test code 
        render_json(post, 1, 'data')
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-26
      • 1970-01-01
      • 2018-09-01
      • 2015-11-27
      相关资源
      最近更新 更多