[技术博客] 如何避免在代码中多重render

作者:马振亚

问题发现

  • 在实际写rails的controller时,一般在controller的最后总是会render一个json供不同的前端使用,当我们一个controller的逻辑在一个方法中写完时,总是能比较轻松的保证一个controller里面有一次render.
  • 但是大多数情况下我们controller需要对用户进行比较多的验证,验证是否具有某种特殊的权限,如果验证失败返回统一的错误json信息(比如没有社长权限等),这种情况下一般会采用单独将验证的代码放置到前置的验证函数中去.
  • 在这个过程中我发现了一个比较棘手的问题,就是在验证失败的时候前面的验证函数会render失败信息,但是返回到主函数之后代码段会继续执行下去,在执行的过程中很容易出现异常或者是再次render一个新的json造成多重render错误.
  • 希望找到一种方法在第一次render之后就能退出避免相关的异常和错误的发生.

方案1 extracted_method and return(父函数and return法)

class Controller
  def show
    verify_order and return
    # even more code over there ...
  end

  private

  def verify_order
    unless @order.awaiting_payment? || @order.failed?
      redirect_to edit_order_path(@order) and return true
    end

    if invalid_order?
      redirect_to tickets_path(@order) and return true
    end
  end
end

这个方法有自身的一些局限性,就是需要在每一个

方案2 子函数yield,父函数调用后{return}

class Controller
  def show
    verify_order{ return }
    # even more code over there ...
  end

  private

  def verify_order
    unless @order.awaiting_payment? || @order.failed?
      redirect_to edit_order_path(@order) and yield
    end

    if invalid_order?
      redirect_to tickets_path(@order) and yield
    end
  end
end

方法需要子函数的每一个render或者重定向点加上yield.

方案3 extracted_method; return if performed?

class Controller
  def show
    verify_order; return if performed?
    # even more code over there ...
  end

  private

  def verify_order
    unless @order.awaiting_payment? || @order.failed?
      redirect_to edit_order_path(@order) and return
    end

    if invalid_order?
      redirect_to tickets_path(@order) and return
    end
  end
end
原文地址:https://www.cnblogs.com/buaareadsun/p/10881816.html