0

我的任务是抽象/继承一个活动记录类。我正在制作一个博客,其中 post 是一个带有标题、slug 日期等的基础超级......你希望找到的所有多余的东西。

这就是事情的转折点,我想将 Post 分成许多其他子帖子类型,例如音频帖子、视频帖子、图像帖子、香草帖子。我认为你说对了。显然每个子类型都有自己的属性和成员。

  1. 不是为每个子帖子类型创建名称、slug 等,而是继承或可能接口基类的最佳实践是什么?(“我更喜欢组合而不是继承”)

  2. 一旦我弄清楚如何正确抽象出我的模型,我想找出一些多态的方式来表达类似 Blog.find(1).posts 的内容并获取所有帖子类型的数组。

我意识到这可能不是以多态方式查询所有帖子类型的最佳性能,因此请随意选择更好的方式。

4

2 回答 2

1

除了单表继承之外,您还可以考虑使用has_one关联。

您的所有子类型都有一个 post-info,它是一般的帖子名称、slug 等(并且 post-info 在多态上属于子类型)。

这样,您将拥有一个发布信息表,以及每个子类型的表。

但是,在模型中你必须做更多的处理:

class PostInfo < ActiveRecord::Base
  belongs_to :post, :polymorphic => true
  # will need these 2 fields: :post_id, :post_type (might be AudioPost, ImagePost, etc)
end

class AudioPost < ActiveRecord::Base
  has_one :post_info, :as => :post

  # you may also want these:
  accept_nested_attributes_for :post_info
  delegate :name, :slug, :posted_at, :to => :post_info
end

所以现在如果你想获得所有的帖子,你可以:

Blog.find(1).post_infos

post_info.post # => audio_post, image_post, or whatever depending on post_type

如果您不想使用.post_infos,您也可以更改所有这些名称,例如:

class Post < ActiveRecord::Base
  belongs_to :actual_post # actual_post_id, actual_post_type
end

class AudioPost < ActiveRecord::Base
  has_one :post, :as => :actual_post
  accept_nested_attributes_for :post
  delegate :name, :slug, :posted_at, :to => :post
end

现在,你有:

posts = Blog.find(1).posts

actual_post = posts.first.actual_post # => an audio_post instance

actual_post.name # => same as actual_post.post.name, so you do not need the name field in the AudioPost model
于 2012-06-02T06:27:32.590 回答
1

虽然我个人也更喜欢组合而不是继承,但 ActiveRecord 不喜欢。在这种情况下,如果您想使用 ActiveRecord 提供的工具,您应该查看Single Table Inheritance,它可以解决您的两个问题。但是,它确实使用了继承。

切换到非 ActiveRecord orm 可能会为您提供一种方法,而无需通过继承完成所有操作。我曾经使用过DataMapper,它更喜欢组合,在过去取得了成功,但它不像 ActiveRecord 那样功能丰富,并且可能无法提供您需要的东西。

于 2012-06-02T04:55:35.577 回答