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

做者:马振亚json

问题发现

  • 在实际写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

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

方案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
相关文章
相关标签/搜索