你如何别名或覆盖范围并调用原文?

时间:2015-09-26 11:09:32

标签: ruby-on-rails scopes

Spree插件添加了范围。让我们说:

class Product
  scope :in_sale, -> { where(in_sale: true) }
end

请注意,actual scope稍微复杂一些。

现在,我想在装饰器中覆盖它:

Spree::Product.class_eval do
  scope :in_sale, -> { on_hand.where(in_sale: true) }
end

而不是复制.where(in_sale: true)的原始实现,我宁愿打电话给原文。

如何重新使用原始范围,有点类似于通常为实例方法调用alias_method_chain :foo, :feature的方式?

1 个答案:

答案 0 :(得分:1)

如果不知道问题背后的原因,我建议使用:

product.in_sale.on_hand

而不是修补Spree::Product类。

如果您仍然需要在一次方法调用中使用此方法,则可以这样做:

Spree::Product.class_eval do
  # alias an old method
  class <<self
    alias_method :old_in_sale, :in_sale
  end

  # reusing old method in a new one
  scope :in_sale, -> { old_in_sale.on_hand }
end

<强>断

此代码似乎有效:

Spree::Product.class_eval do
  old_in_sale = in_sale

  # reusing old method in a new one
  scope :in_sale, -> { old_in_sale.on_hand }
end

正如@berkes在下面的评论中指出的那样,它仅对old_in_sale进行一次评估,并且该值将来会被重用。它仍然可能产生正确的结果,但它并不保证。