scribble

吕小荣

Blog Friends RSS About

Rails 多态的两种使用场景

8 February, 2015

本文是我总结的 Rails 多态的两种使用场景

场景1: 多个类(Post/Photo/Article) 与某个类 (comment)的关系为 1:n

我们的业务中经常会碰到这种场景。

Post、Photo、Article 都可以被评论,他们与 Comment 的关系为

Post(1) : Comment(n)  
Photo(1) : Comment(n)  
Article(1) : Comment(n)  

如果定义三个 Comment 类,会十分啰嗦。这时候就可以使用Polymorhpic 来优雅的实现。

class Post
  has_many :comments, as: :commentable
end


class Article
  has_many :comments, as: :commentable
end


class Photo
  has_many :comments, as: :commentable
end


class Comment
  belongs_to :commentable, ploymorphic: true
end

后来和瓜哥、治民交流的时候,他们经常说,可以使用多态来替代 Single Table Inheritance (STI)。我总是难以理解, STI 和多态解决的是两种业务场景呀?

后来看了 Ryan Bates 在某一期 Railscast 中的讲解才豁然开朗,原来多态还可以这么玩。

场景2: 替代 Single Table Inheritance (STI)

我们可以使用 STI 可以把父类,子类的数据放到一张表里。但随着业务的膨胀,子类和父类的差别可能会越来越多。

所以,当我在 STI 和 多态之间犹豫不决的时候,会拿这个标准来衡量:如果能预见到未来不可避免的差异(超过三个字段),一开始就不选用 STI,而是选用多态。

这是 Railscast 中的一个范例,非常具有代表性。

class User < ActiveRecord::Base
  has_many :tasks, dependent: :destroy
  belongs_to :profile, polymorphic: true
end


class GuestProfile < ActiveRecord::Base
  has_one :user, as: :profile, dependent: :destroy
end


class MemberProfile < ActiveRecord::Base
  has_one :user, as: :profile, dependent: :destroy
end

Polymorphic

参考资料

Railscast: STI and Polymorphic Associations