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

时间:2015-01-08 22:01:23

标签: ruby-on-rails module include mixins

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

我有一个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

1 个答案:

答案 0 :(得分:1)

通常,在Rails中,这种数据模型将通过单表继承(通常缩写为STI)来完成。您将拥有一个Order类(以及数据库中相应的orders表),它将具有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/