Rails——单表继承中的多态性



我有三个模型,PoemSongUser。用户可以对任意数量的诗歌和歌曲进行投票。

一种解决方案是制作两个关联模型PoemVoteSongVote

class PoemVote
attr_accessible :poem_id, :user_id
belongs_to :poem
belongs_to :user
end
class SongVote
attr_accessible :song_id, :user_id
belongs_to :song
belongs_to :user
end

我可以呼叫some_poem_vote.poemsome_song_vote.song

然而,PoemVoteSongVote本质上是相同的。如何使用单表继承来扩展父级Vote类中的两个?

我正沿着以下思路思考:

class Vote
attr_accessible :resource_id, :user_id
end
class PoemVote < Vote
...not sure what goes here...
end
class SongVote < Vote
...not sure what goes here...
end

我如何让它工作,这样我仍然可以调用some_poem_vote.poem,但下面让PoemVotes和SongVotes共享一个数据库表?或者我的问题有更好的解决方案吗?

在rails中,STI很简单:只需在votes表上创建一个type字符串列,rails即可处理其余部分。要创建正确的关联,可以执行以下操作:

class Vote
attr_accessible :user, :votable
belongs_to :user
belongs_to :votable, polymorphic: true
end

这将需要在CCD_ 16表上添加CCD_ 14和CCD_。一定要添加

has_many :votes, as: :votable, class_name: 'PoemVote' # or 'SongVote'

在您的关联模型上。然而,这种方法的问题是,您必须保持警惕,不要直接使用Vote来创建投票,否则您将有错误类型的投票关联。为了加强这一点,有一种可能的黑客攻击:

class Vote
attr_accessible :resource_id, :user_id
def self.inherited( subclass )
super( subclass )
subclass.send :belongs_to, :votable,
class:  "#{subclass.name.gsub('Vote','')}"
end
end

但我确信(我也遇到过同样的问题),这为代码恐怖打开了大门,因为你必须解决许多由继承引起的问题(作用域行为怪异,一些库不能很好地管理STI,等等)

问题是:你真的需要科技创新吗?如果你的选票表现相同,不用麻烦使用STI,只需使用多态的belongs_to,你就会省去很多麻烦。

最新更新