非常感谢回答我的每一个人,但是我认为我已经成功通过使用jystewart的Rails 3版本的acts_as_polymorphs gem来修复了这个问题。
以下是我所做的:
让我们回忆一下,我们有帖子和四种不同类型的片段。那就是6个不同的模型(post.rb、snippet.rb、code.rb、text.rb、image.rb和video.rb)。
- 帖子拥有多个片段。
- 片段属于帖子。
- 代码、文本、视频和图像都是片段的一种类型。
而且最大的问题是我们不知道片段是哪种类型的对象,因为它可以是4种不同的东西之一。
起初,我尝试使用单一表继承来解决这个问题,但是在我看来,这些对象(代码、文本、视频和图像)彼此之间的区别太大,无法很好地工作,而且我不喜欢它可能会导致许多空数据库单元格的事实,所以我选择了多态路线。
我在这里无法使用标准的多态关联,因为这不是您通常遇到的多态情况。通常,在处理多态性时,我们谈论的是像评论模型这样的东西,它可以附加到多个其他模型上。多态实体始终是相同的东西。但在这种情况下,我们正在讨论可以是4种不同事物之一的片段模型。这不是一个简单的belongs_to情况。多态性没有发生。
然后我偶然发现了m.onkey.org上的这篇文章 - 虽然已经过了几年,但他基本上解释了这种情况需要acts_as_polymorphs gem。
所以解决方案是执行以下操作:
- 我创建了6个模型,所有模型都扩展了ActiveRecord :: Base
- 将
has_many_polymorphs
添加到post模型中
- 在snippet模型中创建了一个多态关联称为“snippetable”
- 通过我的迁移文件向snippets表添加了一些新字段
这是我的代码:
class Post < ActiveRecord::Base
has_many_polymorphs :snippets, :from => [:codes, :texts, :videos, :images], :through => :snippets
end
class Snippet < ActiveRecord::Base
belongs_to :snippetable, :polymorphic => true
end
class Code < ActiveRecord::Base
end
class Text < ActiveRecord::Base
end
class Video < ActiveRecord::Base
end
class Image < ActiveRecord::Base
end
我们需要的另一件事,就是在CreateSnippets迁移中添加一些新字段:
class CreateSnippets < ActiveRecord::Migration
def self.up
create_table :snippets do |t|
t.references :post
t.column :snippetable_id, :integer, :null => false
t.column :snippetable_type, :string, :null => false
t.timestamps
end
end
end
就是这样!难以置信,现在我可以进入Rails控制台并执行以下操作:
p = Post.first
p.codes << Code.create(:code=>"This is a code snippet")
p.images << Image.create(:image=>"xyz.png")
p.images << Image.create(:image=>"123.png")
p.codes.count
p.images.count
p.snippets.count
雅尔蒂!
无论如何,花了我11天才解决这个问题,我真的很沮丧我无法解决它。我希望这能帮助到某些人。
以下是一些关于acts_as_polymorph的不错阅读资料:
真是漫长的过程