Rails 谁能分享一下 rails 里面的 STI 和 Polymorphic Association 的区别和适用范围?

zlx_star · 2013年03月25日 · 最后由 zlx_star 回复于 2013年03月26日 · 3999 次阅读

看到新项目里面使用了 STI 和 Polymorphic Association

之前自己一直是使用 Polymorphic Association,对 STI 了解不多。自己 google 了一下,感觉还是很迷糊。

谁能分享一下两者的区别和适用范围?

你想问的是 STIPolymorphic Association 的区别还是 STIPolymorphic 的区别?

..,看标题我还以为又是什么高端技术..

@zlx_star 好久不见,改下错别字。。

#1 楼 @kenshin54 不好意思,没表达清楚,是 STI 和 Polymorphic Association。你能分享一下吗?

#2 楼 @jjym 不好意思,标题没表达清楚

#3 楼 @feitian124 改了,惭愧。现在还在上海工作吗?

#4 楼 @zlx_star

理论的说不清,拿实际例子说说

比如你有 User,想细分一个 Guest 出来,Guest 有自己的一堆业务逻辑,但是他的结构和 User 是一致的。可以考虑用 STI,STI 的 model 在数据库只会用一张表,表中会用 type 来表示类型,也就类名。

Polymorphic Association,看名字就知道是用在关联上的,这个例子太多了,比如 Tag,Picture,Comment,用户可以有 tag,产品可以有 tag,文章可以有 tag,Tag 本身是一个 model,但是其他 model 都会用到它,这时候可以用 Polymorphic Association。通常会写成 taggable, imageable, commentable,数据库里会有一个 xxx_type 和 xxx_id,来表示关联者的类型和其实例的 id。

屌丝级别分析完毕,求大神布道理论知识。

#7 楼 @kenshin54 STI 共用一张表,那就是说 Guest 也可以获得所有数据?另外,如果你用 User.find(:id) 找出一条记录,Rails 会自动将它转化为 Guest 吗?

#8 楼 @zlx_star 不会,Guest 只能查出 type 是 Guest 的数据,User.find 会转化为 Guest

关系数据库是没有继承一说的,而面向对象设计里会有父子类继承关系,也就是 @kenshin54 举得 User 和 Guest 关系,映像到数据库里我们用一个字段“type”来表示是父类还是子类,是一种标准模式,而其他属性则是以 column 形式存在,所以很容易会出现冗余,毕竟某些属性是某个类特有的,理论参考 Martin Fowler 的 Patterns of Enterprise Application Architecture 一书。DHH 在设计 Rails 框架的时候是深受 Martin Fowler 的模式设计影响,基本都能从该书中找到参考。

Polymorphic Association 要表达的不是继承关系,而是组合关系,@kenshin54 举得例子很好。可以看看 Inheritance VS Composition 的比较。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号