0

我正在开发一个在线商店,客户需要能够删除订单并自动补货(例如,测试订单)。这是我第一次尝试实现这个:

class Order < ActiveRecord::Base
  def destroy_and_restock
    restock_products
    destroy
  end

  protected

  def restock_products
    line_items.each do |li|    
      li.product.quantity_on_hand += li.quantity
      li.product.save
    end
  end
end

但是如果我以后需要创建另一个destroy_and_x方法怎么办?为什么不允许将 X 作为参数传递给destroy()方法?所以现在我正在考虑这样做:

alias :old_destroy :destroy
def destroy(options = {})
  if options['restock'] == true
    restock_products
  end
  old_destroy
end

protected

def restock_products
  line_items.each do |li|    
    li.product.quantity_on_hand += li.quantity
    li.product.save
  end

这更具扩展性,但让我觉得有点脏。我觉得脏是错的吗?有没有更好的方法来做到这一点?

4

4 回答 4

2

我会说“是的,这很脏”。您的意图不是修改“销毁”方法的行为,而是做一些特定于域的工作,然后运行destroy​​. 你的第一种方法很棒——定义一个做你想做的事情的方法,并destroy根据需要调用。我认为,正如您正在考虑的那样,“包装”或“猴子修补”方法是一种最适用于无法使用标准 OO 方法的技术 - 例如,当您需要修改/增强行为时在您的控制范围之外定义和使用的类。

即使您正在考虑修改destroy方法本身的行为,我也建议您在此处覆盖该方法,而不是包装它:

def destroy(options = {})
  restock_products if options['restock']
  super() # I think parens are necessary here, to avoid passing options up the chain
end
于 2009-06-16T04:19:48.503 回答
0

只使用一个块怎么样?然后你不必在课堂上设计这个时把头发分开,你可以在需要时做更多:

def destroy_after &block
  yield if block
  destroy
end

然后像这样调用它:

order.destroy_after { order.restock_products }

我想不出这个函数的好名字……但我希望你能明白。

于 2009-06-16T04:48:57.807 回答
0

贺拉斯,我误解了你的问题。我想你正在寻找这个:

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

现在您可以保护您的方法并添加任意数量的 before_destroy 内容。希望这对您有用,而不会压倒破坏。

祝你好运。

于 2009-06-16T10:20:32.950 回答
0

如果猴子补丁不能让您在晚上睡觉,您可以通过子类化来实现相同的目的。当我需要快速破解或快速调试破解时,我也会使用猴子补丁。

于 2009-06-16T10:24:43.207 回答