【问题标题】:has_many polymorphism/inheritance in RailsRails 中的 has_many 多态/继承
【发布时间】:2013-10-27 23:18:23
【问题描述】:

我正在尝试在 Rails 中建立多态关系,但遇到了一些困难。这是我的数据模型:

class Order
    has_many :order_items
end

class OrderItem
    belongs_to :order
end

class PhysicalItem < OrderItem
end

class VirtualItem < OrderItem
end

PhysicalItem 和 VirtualItem 在它们的模型中有足够的差异,以保证被拆分到它们自己的表中。所以,我设想有:

订单表

physical_items 表

一个 virtual_items 表

一个 order_items 表,其中 item_type = ["PhysicalItem" or "VirtualItem"] 和对应表中匹配行的 item_id。

我最终希望能够编写这样的代码:

order = Order.new
physical_item = PhysicalItem.new
virtual_item = VirtualItem.new

order.order_items << physical_item
order.order_items << virtual_item

puts order.order_items
# Should list out the physical item and then the virtual item.

理论上看起来很简单,但总体上看来对这种结构的支持并不多。有人对使用 ActiveRecord 在 postgresql 数据库中实现这一点有任何想法吗?

【问题讨论】:

  • PhysicalItemVirtualItem 从产品继承时,我在您的列表中没有看到产品型号?它在哪里适合所有这些?
  • 我想我并不真的需要产品模型 - 我从中得到的唯一东西是能够查询 order.products 然后检索一堆混合的 PhysicalItems 和 VirtualItems。
  • 另外,我编辑了我的问题以反映我更新的对象名称 - 抱歉之前的混淆。
  • 如果您使用不同的表,请考虑使用使 MTI 更容易的 gem。

标签: ruby-on-rails inheritance activerecord polymorphism rails-postgresql


【解决方案1】:

您不应该为此需要多态关联。 Order 模型中的方法也可以正常工作:

class Order < ActiveRecord::Base
  has_many :physical_items
  has_many :virtual_items

  def order_items
    physical_items + virtual_items
  end
end

class PhysicalItem < ActiveRecord::Base
  belongs_to :order
end

class VirtualItem < ActiveRecord::Base
  belongs_to :order
end

您还需要physical_itemsvirtual_items 表都具有order_id 列。然后,复制您想要的行为:

order = Order.new
physical_item = order.physical_items.new
virtual_item = order.virtual_items.new

puts order.order_items

【讨论】:

  • 当然,但是假设有人在他们的购物车中添加了 30 种不同的商品。我想选择他们添加的前 10 个项目 - 如果不查询所有项目、按 created_at 时间戳对最终列表进行排序,然后丢弃其他模型,我就无法做到这一点。这将是一个非常缓慢的操作。
【解决方案2】:

您可以将 PostgreSQL HStore 数据类型与 STI 结合使用。通过这种方式,您可以获得在一个表上运行单个 SELECT 的好处,但该表不会被特定类型的列污染。

然后您将只有两个表:

  • 订单表
  • order_items 表

对于 order_items 表,迁移将包括:

class CreateOrderItemsTable < ActiveRecord::Migration
  def change
    create_table :order_items do |t|
      t.integer :order_id
      t.string :type
      t.hstore :data
    end
  end
end

您的模型将如下所示:

class Order
  has_many :order_items
end

class OrderItem
  belongs_to :order
  serialize :data, ActiveRecord::Coders::Hstore
end

class PhysicalItem < OrderItem
end

class VirtualItem < OrderItem
end

我尝试使用多态连接表,但它仍然需要太多的 SQL 查询才能获得关联列表。 HStore 与 STI 是一个很好的组合。欲了解更多信息,请阅读:http://www.devmynd.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多