ruby class_eval和开放类

pjngdqdw  于 2024-01-07  发布在  Ruby
关注(0)|答案(3)|浏览(163)

我正在使用Spree,Spree有一个名为Order的类,看起来像:

module Spree
  class Order
    # class definition.
  end
end

字符串
在我自己的应用程序中,我一直像这样定制Order

Spree::Order.class_eval do
  # customisations
end


我的问题是,我可以这样做吗:

module Spree
  class Order
    # My own customisations.
  end
end


这有什么缺点吗?本质上,我想避免使用class_eval

rseugnpd

rseugnpd1#

Benjamin,如果现有的类不存在或未加载,reopen class不会通知您(但class_eval会引发错误)。
但是如果你有测试覆盖率,我猜重新打开类应该是安全的?
请参阅https://stackoverflow.com/a/900508/474597以获得更详细的解释。

yhuiod9q

yhuiod9q2#

没有class_eval,你不能改变类。只要尝试覆盖一个方法,所有其他方法都消失了。使用class_eval,你可以避免它。这是ruby的方式。

mzillmmw

mzillmmw3#

还有另一种方法可以解决这个问题,它在Spree的情况下工作得很好。我想我会把这个答案留给其他与Spree一起工作的人。
您可以使用prepend来“安排"在Spree最终加载的任何时间重新打开类。

module Spree
  # Decorates Spree::Order
  module OrderDecorator
    CANCELLATION_STATES = %w[canceled pre_canceled].freeze

    def self.prepended(base)
      base.belongs_to :delivery, class_name: 'Delivery', foreign_key: 'delivery_id', optional: true
      base.scope :deliverable, lambda { }
    end
  end
end

Spree::Order.prepend Spree::OrderDecorator

字符串
如果你的装饰器模块有太多的方法,你可以也应该使用multiple并控制prepend的顺序。

Spree::Order.prepend Spree::OrderDecorator
Spree::Order.prepend Admin::SpreeOrderAdminable

相关问题