Ruby on rails 如何别名或重写作用域并调用原始作用域?
Spree插件添加了一个作用域。比如说:Ruby on rails 如何别名或重写作用域并调用原始作用域?,ruby-on-rails,scopes,Ruby On Rails,Scopes,Spree插件添加了一个作用域。比如说: class Product scope :in_sale, -> { where(in_sale: true) } end 请注意,这个过程稍微复杂一些 现在,我想在我的装饰器中覆盖它: Spree::Product.class_eval do scope :in_sale, -> { on_hand.where(in_sale: true) } end 我宁愿调用原始的。where(in_sale:true),而不是复制的原始实
class Product
scope :in_sale, -> { where(in_sale: true) }
end
请注意,这个过程稍微复杂一些
现在,我想在我的装饰器中覆盖它:
Spree::Product.class_eval do
scope :in_sale, -> { on_hand.where(in_sale: true) }
end
我宁愿调用原始的。where(in_sale:true)
,而不是复制的原始实现
您如何重新使用原始范围,这与您通常调用
别名\u方法\u chain:foo,:feature
作为实例方法的方式类似?在不知道问题背后的原因的情况下,我建议使用:
product.in_sale.on_hand
而不是修补Spree::Product
class
如果在一次方法调用中仍需要此功能,可以这样做:
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
正如@berkes在下面的评论中所指出的,它只对
old_in_sale
计算一次,并且这个值将在将来重新使用。它仍然可能产生正确的结果,但不能保证。Hm,普通别名不起作用吗?@SergioTulentsev,是的。由于类eval的原因,这比在实例方法上定义别名稍微复杂一些。也许你可以用一些代码来回答这个问题,这样我们就可以结束这个问题了。old_in_sale=self.in_sale
不会触发实际的进程,而是让old_in_sale
包含产品列表,而不是指向范围的指针吗?@berkes你是对的。我已经更新了我的答案。顺便说一句,旧代码在简单的情况下仍然表现良好old_in_sale
包含在每个查询中重复使用的ActveRecord::Relation
。但是,如果旧的销售中的返回的内容与我们第一次执行时得到的内容不同,它将被打破。
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