简体   繁体   English

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

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

In the rails app I am working on I have a model Order, Order technically has 2 types (newspaper and web) but they are both represented in the Order Model. 在我正在使用的rails应用程序中,我有一个订单模型,订单在技术上有两种类型(报纸和网络),但它们都在订购模型中表示。 The children below Order are different based on the type of Order and thus the methods used to obtain data about the orders are different. Order的子级根据Order的类型而不同,因此用于获取有关订单数据的方法也不同。

I have a CurrentMonthsOrders serializer where I would like to be able to call: 我有一个CurrentMonthsOrders序列化器,我可以在其中调用:

 order.start_date
 order.end_date

without having to check what type of Order I am dealing with. 无需检查我正在处理的订单类型。 So what I would like to be able to do is include the module based on the type of Order I am dealing with. 所以我想做的就是根据我要处理的订单类型添加模块。 Is this possible/is this the best way to go about this problem? 这可能/这是解决此问题的最佳方法吗?

Below are the modules: 以下是模块:

  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

Typically, in Rails, this sort of data model would be done via Single Table Inheritance (often abbreviated STI). 通常,在Rails中,此类数据模型将通过“单表继承”(通常缩写为STI)来完成。 You would have an Order class (and corresponding orders table in the database), which would have a type column. 您将拥有一个Order类(以及数据库中的相应orders表), type具有一个type列。 Then you would define subclasses of Order for WebOrder and Newspaper: 然后,您将为WebOrder和Newspaper定义Order的子类:

class WebOrder < Order
  def start_date
    ...
  end

  ...
end

class Newspaper < Order
  ...
end

When WebOrder or Newspaper orders are saved to the database, Rails will record the class in the type column, and when records are pulled from the database, Rails will use the type column to create instances of the correct subclass. 当WebOrder或Newspaper订单保存到数据库时,Rails将在type列中记录该类,而当从数据库中提取记录时,Rails将使用type列创建正确子类的实例。

It is possible to add the methods of a module to a particular instance of a class, but I wouldn't recommend it in general, because then you have objects which are ostensibly the same class, but have different code/behavior. 可能一个模块的方法添加到一个类的特定实例,但我不会推荐它在一般情况下,因为那时你有表面上是相同的类的对象,但有不同的代码/行为。 Also, it can lead to higher memory usage, since you are customizing many individual objects. 此外,由于您要自定义许多单个对象,因此可能导致更高的内存使用率。 But if you were to do it, it would work roughly like this: 但是,如果要这样做,它将大致像这样工作:

 order = Order.new
 order.extend(Newspaper)

You'd have to remember to do that sometime between loading your Order instance and calling the customized methods, though. 不过,您必须记住在加载Order实例和调用自定义方法之间的某个时间这样做。 If you use Single Table Inheritance, Rails will take care of it for you. 如果您使用单表继承,Rails会为您处理。

There's a pretty good explanation of Single Table Inheritance here: http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-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