繁体   English   中英

有条件地包含基于Ruby on Rails模型实例的模块

[英]Conditionally Include a Module based on the Instance of a Model Ruby on Rails

在我正在使用的rails应用程序中,我有一个订单模型,订单在技术上有两种类型(报纸和网络),但它们都在订购模型中表示。 Order的子级根据Order的类型而不同,因此用于获取有关订单数据的方法也不同。

我有一个CurrentMonthsOrders序列化器,我可以在其中调用:

 order.start_date
 order.end_date

无需检查我正在处理的订单类型。 所以我想做的就是根据我要处理的订单类型添加模块。 这可能/这是解决此问题的最佳方法吗?

以下是模块:

  module WebOrder

    def start_date
      web_line_items.sort_by(&:start_date).first.start_date
    end

    def end_date
      web_line_items.sort_by(&:end_date).last.end_date
    end

  end

  module Newspaper

    def start_date
      newspaper_placements.last.date.strftime('%m/%d')
    end

    def end_date
      object.newspaper_placements.first.date.strftime('%Y/%-m/%-d')
    end

  end

通常,在Rails中,此类数据模型将通过“单表继承”(通常缩写为STI)来完成。 您将拥有一个Order类(以及数据库中的相应orders表), type具有一个type列。 然后,您将为WebOrder和Newspaper定义Order的子类:

class WebOrder < Order
  def start_date
    ...
  end

  ...
end

class Newspaper < Order
  ...
end

当WebOrder或Newspaper订单保存到数据库时,Rails将在type列中记录该类,而当从数据库中提取记录时,Rails将使用type列创建正确子类的实例。

可能一个模块的方法添加到一个类的特定实例,但我不会推荐它在一般情况下,因为那时你有表面上是相同的类的对象,但有不同的代码/行为。 此外,由于您要自定义许多单个对象,因此可能导致更高的内存使用率。 但是,如果要这样做,它将大致像这样工作:

 order = Order.new
 order.extend(Newspaper)

不过,您必须记住在加载Order实例和调用自定义方法之间的某个时间这样做。 如果您使用单表继承,Rails会为您处理。

这里对单表继承有一个很好的解释: http : //eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM