[技術博客] 如何避免在代碼中多重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
相關文章
相關標籤/搜索