Ruby on rails Rails中有很多多态性/继承

Ruby on rails Rails中有很多多态性/继承,ruby-on-rails,inheritance,activerecord,polymorphism,rails-postgresql,Ruby On Rails,Inheritance,Activerecord,Polymorphism,Rails Postgresql,我试图在Rails中建立多态关系,但遇到了一些困难。以下是我的数据模型: class Order has_many :order_items end class OrderItem belongs_to :order end class PhysicalItem < OrderItem end class VirtualItem < OrderItem end 类顺序 有很多:订购物品 结束 类OrderItem 属于:秩序 结束 类PhysicalItem

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

class Order
    has_many :order_items
end

class OrderItem
    belongs_to :order
end

class PhysicalItem < OrderItem
end

class VirtualItem < OrderItem
end
类顺序
有很多:订购物品
结束
类OrderItem
属于:秩序
结束
类PhysicalItem
PhysicalItem和VirtualItem在其模型中有足够的差异,足以保证将其拆分到各自的表中。因此,我设想:

点菜台

物理项目表

虚拟项目表

order_items表,其item_type=[“PhysicalItem”或“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.
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
order=order.new
物理项=PhysicalItem.new
虚拟项=VirtualItem.new

order.order\u items您不应该为此需要多态关联。
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

您不应该为此需要多态关联。
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

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

然后,您将只有两个表:

  • 订单表
  • 订单项目表
对于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 CreateOrderItemsTable
然后,您的模型将如下所示:

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.
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
类顺序
有很多:订购物品
结束
类OrderItem
属于:秩序
序列化:数据,ActiveRecord::Coders::Hstore
结束
类PhysicalItem

我尝试使用多态联接表,但它仍然需要太多SQL要求才能获得关联列表。HStore与STI是一个很好的组合。有关更多信息,请阅读以下内容:

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

然后,您将只有两个表:

  • 订单表
  • 订单项目表
对于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 CreateOrderItemsTable
然后,您的模型将如下所示:

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.
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
类顺序
有很多:订购物品
结束
类OrderItem
属于:秩序
序列化:数据,ActiveRecord::Coders::Hstore
结束
类PhysicalItem

我尝试使用多态联接表,但它仍然需要太多SQL要求才能获得关联列表。HStore与STI是一个很好的组合。有关更多信息,请阅读以下内容:

PhysicalItem
VirtualItem
继承自产品时,我在您的列表中没有看到产品型号?它在哪里适合所有这些?我想我真的不需要产品模型-我从中得到的唯一东西是能够查询order.products,然后检索大量混合物理项和虚拟项。此外,我编辑了我的问题来反映我更新的对象名称-抱歉之前的混乱。如果你使用不同的表考虑使用一个使MTI更容易的宝石。当<代码>物理项< /代码>和<代码> ViualItIs<代码>从产品继承时,我在你的列表中没有看到一个产品模型吗?它在哪里适合所有这些?我想我真的不需要产品模型-我从中得到的唯一东西是能够查询order.products,然后检索大量混合物理项和虚拟项。此外,我编辑了我的问题来反映我更新的对象名称-抱歉之前的混乱。如果你使用不同的表考虑使用一个宝石,使MTI更容易。当然,但让我们说,有人增加了30个不同的项目到他们的购物车。我想选择他们添加的前10个项目——如果不查询所有项目,按照创建的时间戳对最终列表进行排序,然后扔掉其他模型,我就无法做到这一点。这将是一个非常缓慢的操作。当然,但假设有人在购物车中添加了30种不同的物品。我想选择他们添加的前10个项目——如果不查询所有项目,按照创建的时间戳对最终列表进行排序,然后扔掉其他模型,我就无法做到这一点。这将是一个非常缓慢的操作。