多态模型hackery

时间:2010-05-12 19:43:28

标签: ruby-on-rails activerecord ruby-on-rails-plugins ruby-on-rails-3

即使我知道,至少据我所知,这不是与ActiveRecord建立关联的默认方式,我正在寻求帮助以实现“hibernatish”多态模型。

例如,请考虑以下基本模型:

# Content only has one property named path
class Content < ActiveRecord::Base
  self.abstract_class = true
end

具体内容:

# Audio only has one property on it's own (duration).
# However, it should also inherit Content's property (path)
class Audio < Content
end

现在,使用ActiveRecord时会发生一些相对有趣的事情,更准确地说是Rails 3 beta 3 ActiveRecord。如果在Content模型上将abstract_class设置为false,则执行以下命令:

Audio.create!(:path => '/dev/null')

它有点从Hibernate的角度来看。也就是说,使用ID 1创建内容记录,并使用ID = 1创建音频记录

然而,问题#1 是为了使其工作,你显然需要关闭abstract_class,这有点打破了这个抽象内容示例的全部要点。

此外,问题#2 是,如果启用abstract_class,则在创建Audio实例时会丢失内容的属性。并且,如果将其关闭,则在创建音频实例时会丢失音频属性。

理想情况下,当面对一个随后被子类化的抽象类时,ActiveRecord将为实例化的具体类提供抽象+具体属性,在本例中为Audio。实际上,这样,在创建音频实例时我们会:

audio = Audio.new #=> <Audio id: nil, duration: nil, path: nil, created_at: nil, updated_at: nil> 

然后[自然]当你指定audio.path ='/ dev / null'并执行保存操作时,ActiveRecord会知道路径属性已被继承,因此需要在父类级别持久化。此外,在同一个保存操作中,如果设置音频的非继承属性,ActiveRecord也会在音频表中保留这些更改。

我的问题是,在介绍之后,人们如何绕过积极的记录并以这种方式加强它?

实际上,我们假设我们正在开发一个旨在通过这种功能提供活动记录的gem。你会怎么做呢?

PS:我实际上正在考虑开发这样的宝石,尽管这样的hackery不应该事先思考。所以,您的反馈最受欢迎。

祝你好运, DBA

1 个答案:

答案 0 :(得分:2)

我知道你在这里会发生什么,但不幸的是我认为你不能按照自己喜欢的方式开箱即用。

基本上,ActiveRecord使用模型继承来做两件事:

  • 抽象类,子类可以从中继承代码和行为但不是表结构。您可以使用#pathContent上实现attr_accessor属性,并且它将由子类继承,但它将持久保存到数据库,除非表格为你的模型子类有一个'path'列。

  • 单表继承,其中子类继承 行为和表持久性。

您可以将两者混合使用,但不存在ActiveRecord模型可以从抽象类继承可持久列的情况。持久化属性和表列之间始终存在1:1映射。