【发布时间】:2009-10-21 05:50:22
【问题描述】:
如何实现活动记录的继承?
例如,我想要一个动物类、狗类和猫类。
模型和数据库表映射如何?
【问题讨论】:
-
你可能想接受一个答案
标签: ruby-on-rails database inheritance activerecord model
如何实现活动记录的继承?
例如,我想要一个动物类、狗类和猫类。
模型和数据库表映射如何?
【问题讨论】:
标签: ruby-on-rails database inheritance activerecord model
Rails 支持单表继承。
来自AR docs:
Active Record 允许继承 将类的名称存储在 默认情况下名为“类型”的列 (可以通过覆盖来改变 Base.inheritance_column)。这表示 继承看起来像这样:
class Company < ActiveRecord::Base; end class Firm < Company; end class Client < Company; end class PriorityClient < Client; end当你执行 Firm.create(:name => “37signals”),这条记录将是 以类型保存在公司表中 =“坚定”。然后,您可以使用 Company.find(:first, "name = '37signals'"),它会返回一个 Firm 对象。
如果您没有类型列 在您的表中定义,单表 不会触发继承。在 这种情况下,它会像平常一样工作 没有特殊魔法的子类 区分它们或 用 find 重新加载正确的类型。
一个很好的教程在这里:http://juixe.com/techknow/index.php/2006/06/03/rails-single-table-inheritance/
【讨论】:
型号:
class Animal < ActiveRecord::Base; end
class Dog < Animal; end
class Cat < Animal; end
迁移:
class CreateAnimals < ActiveRecord::Migration
def self.up
create_table :animals do |t|
# Other attributes...
t.string :type
end
end
def self.down
drop_table :animals
end
end
【讨论】:
ActiveRecord 支持将继承层次结构映射到单个表(Single-table inheritance。表将有一个列type 存储实际类的名称并用于选择其他特定于类的列。
可以实现多表继承映射,如here 所示,但这种特殊方式不可移植,AFAIK。
【讨论】:
一种特殊的方法是通过Delegated Types - 如果您希望能够对所有动物进行分页,并同时查看猫和狗,那么委托类型特别有用。我也喜欢它,因为你不需要有空列,因为它没有意义,就像单表继承解决方案一样。
# Schema: entries[ id, created_at, updated_at, animalable_type, animalable_id ]
class Animal < ApplicationRecord
delegated_type :animalable, types: %w[ Cat Dog ]
end
module Animalable
extend ActiveSupport::Concern
included do
has_one :animal, as: :animalable, touch: true
end
end
# Schema: cats[ id, selfishness_level ]
class Cat < ApplicationRecord
include Animalable
end
# Schema: dogs[ id, favourite_game, wag_tail_level ]
class Dog < ApplicationRecord
include Animalable
end
【讨论】: