【问题标题】:Ruby Actions: How to avoid a bunch of returns to halt execution?Ruby Actions:如何避免一堆返回来停止执行?
【发布时间】:2010-03-13 22:43:59
【问题描述】:

如何干燥下面的代码?我必须设置一堆 ELSE 吗?我通常会找到“如果遇到,停止”,“如果遇到,停止”,而不是一堆嵌套的 if。

我发现redirect_to 和render 不会停止动作执行...

def payment_confirmed    
  confirm_payment do |confirmation|    
    @purchase = Purchase.find(confirmation.order_id)
    unless @purchase.products_match_order_products?(confirmation.products)
      # TODO notify the buyer of problems
      return
    end

    if confirmation.status == :completed
      @purchase.paid!                     
      # TODO notify the user of completed purchase
      redirect_to purchase_path(@purchase)
    else      
      # TODO notify the user somehow that thigns are pending
    end   

    return
  end

  unless session[:last_purchase_id]
    flash[:notice] = 'Unable to identify purchase from session data.'
    redirect_to user_path(current_user) 
    return
  end

  @purchase = Purchase.find(session[:last_purchase_id]) 

  if @purchase.paid?
    redirect_to purchase_path(@purchase)       
    return
  end

  # going to show message about pending payment
end

【问题讨论】:

    标签: ruby-on-rails dry actionview


    【解决方案1】:

    您可以执行以下操作来减少代码。

    1) 使用

    return redirect_to(..)
    

    而不是

    redirect_to(..)
    return
    

    2) 将flashredirect_to 代码提取到通用方法中。

    def payment_confirmed    
      confirm_payment do |confirmation|    
        @purchase = Purchase.find(confirmation.order_id)        
        return redirect_with_flash(...) unless @purchase.products_match_..(..)
    
        return redirect_with_flash(...) unless confirmation.status == :completed
    
        @purchase.paid! 
        return redirect_to(...)
      end
    
      return redirect_with_flash(...) unless session[:last_purchase_id]      
    
      @purchase = Purchase.find(session[:last_purchase_id]) 
      return redirect_to(...) if @purchase.paid?
    
      # going to show message about pending payment
    end
    

    创建一个新方法以在显示 Flash 消息后重定向到给定的 url。

    def redirect_with_flash url, message
      flash[:notice] = message
      redirect_to(url)
    end
    

    注意为了便于阅读,我在某些地方截断了上面的代码。

    【讨论】:

    • 你好坎达达。认为可以重构代码以避免提前返回?
    • 结合returnredirect_to 已经减少了冗余。你能在你的问题中提供更多细节吗?
    【解决方案2】:

    and return false 添加到redirect_to 的末尾或render 以在该点停止执行。这应该有助于为您清理工作。

    【讨论】:

    • 返回 false 会导致 Rails 不渲染?
    【解决方案3】:

    您还可以将这些步骤分解为单独的方法。所以结束代码看起来像:

    def payment_confirmed    
      confirm_payment do |cnf|    
        confirmation_is_sane?(cnf) && purchase_done?(cnf)
        return
      end
      has_last_purchase? && last_purchase_paid?
    end
    

    对于一个看起来像这样的保理:

    def confirmation_is_sane?(confirmation)
       @purchase = Purchase.find(confirmation.order_id)
       unless @purchase.products_match_order_products?(confirmation.products)
         # TODO notify the buyer of problems and render
          return false 
        end
       true
    end 
    def purchase_done?(confirmation)
       if confirmation.status == :completed
          @purchase.paid!                     
          # TODO notify the user of completed purchase
          redirect_to purchase_path(@purchase)
          return false
        else      
          # TODO notify the user somehow that thigns are pending and render
          return true
        end   
    end
    def has_last_purchase?
      unless session[:last_purchase_id]
        flash[:notice] = 'Unable to identify purchase from session data.'
        redirect_to user_path(current_user) 
        return false
      end
    
      @purchase = Purchase.find(session[:last_purchase_id]) 
      return true
    end
    def last_purchase_paid?
      if @purchase.paid?
        redirect_to purchase_path(@purchase)       
        return false
      end
      # going to show message about pending payment
      return true
    end
    

    这基本上只是使用 true/false 和 && 来提前退出而不是使用 return,但对我来说,它似乎更容易阅读。您仍然需要在其他方法中调用 render,但这应该没什么大不了的。

    确认订单和最后一次购买之间的区别似乎也很奇怪,但这也许是 confirm_payment 工作方式的产物。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 2021-10-18
      • 2014-04-17
      相关资源
      最近更新 更多