我的任务是抽象/继承活动记录类。我正在制作一个博客,其中帖子是一个基础超级标题,slug日期等...你期望找到的所有冗余的东西。
这里的事情发生了变化,我希望将Post发布到许多其他子帖子类型中,例如音频帖子,视频帖子,图片帖子,香草帖子。我认为你说对了。显然,每个子类型都有各自的属性和成员。
不是为每个子帖子类型创建名称,slug等,而是继承或可能与基类接口的最佳做法是什么? (“我赞成作品而不是继承”)
一旦我弄清楚如何正确地抽象出我的模型,我想找出一些多态的方式来表达像Blog.find(1).posts这样的东西并获得所有帖子类型的数组。
我意识到这可能不是以多态方式查询所有帖子类型的性能最佳,因此可以随意采用更好的方式。
答案 0 :(得分:1)
虽然我个人也喜欢构图而不是继承,但ActiveRecord却没有。在这种情况下,如果您想使用ActiveRecord提供的工具,您应该查看Single Table Inheritance,这将解决您的两个问题。但它确实使用了继承。
切换到非ActiveRecord orm可能会为您提供一种方法,而无需通过继承执行所有操作。我曾经使用了DataMapper,它更喜欢构图,过去很成功,但它不像ActiveRecord那样功能丰富,可能无法满足您的需求。
答案 1 :(得分:1)
除了单表继承之外,您还可以考虑使用has_one
关联。
所有子类型都有一个post-info,即一般帖子名称,slug等(并且post-info属于多态的子类型)。
通过这种方式,您将拥有一个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