1

我怎样才能干燥下面的代码?我必须设置一堆 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
4

3 回答 3

3

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

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

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

于 2010-03-13T23:59:03.130 回答
0

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

于 2010-03-13T22:51:24.453 回答
0

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

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 工作方式的产物。

于 2010-04-26T08:26:35.877 回答