别名方法不受欢迎吗?

时间:2009-06-16 03:49:34

标签: ruby-on-rails e-commerce alias

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

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 个答案:

答案 0 :(得分:2)

我会说“是的,这很脏。”您的目的不是要修改'destroy'方法的行为,而是要做一些特定于域的工作,然后运行destroy。您的第一种方法很棒 - 定义一个可以满足您需求的方法,并根据需要调用destroy。我认为,正如您所考虑的那样,“包装”或“猴子修补”方法是一种在无法使用标准OO方法时最佳应用的技术 - 例如,当您需要修改/增加行为时在您的控制范围之外定义和使用的类。

即使你 考虑修改destroy方法本身的行为,我建议覆盖这里的方法,而不是包装它:< / p>

def destroy(options = {})
  restock_products if options['restock']
  super() # I think parens are necessary here, to avoid passing options up the chain
end

答案 1 :(得分:0)

如何使用一个块?然后你在课堂上设计时不必拉开头发,你可以在需要的时候做更多的事情:

def destroy_after &block
  yield if block
  destroy
end

然后这样称呼:

order.destroy_after { order.restock_products }

我想不出这个功能的好名字......但我希望你明白这个想法。

答案 2 :(得分:0)

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

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

现在您可以保护您的方法并添加尽可能多的before_destroy事物。希望这对你有用而不会超越毁灭。

祝你好运。

答案 3 :(得分:0)

如果猴子修补不能让你在晚上睡觉,你可以通过子类化来实现同样的目的。当我需要快速入侵或快速调试时,我也会修补补丁。