我有一个模型“Collection”,它与其他 3 个模型具有 has_many_through 关系:“Song”、“Album”和“Artist”,通过连接表“Collectionitems”实现(fwiw collectionitem 是多态的,因此 has_many 声明中的 source 选项在下面的例子中。)
我想要完成的是确保放入连接表中的记录是唯一的(不同的),以便没有不必要的巨大表并且明显不处理重复项。
我的第一次尝试部分奏效了。
has_many :albums, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Album"
has_many :artists, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Artist"
has_many :songs, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Song"
这确实处理了 uniq 方面,但是如果我尝试添加集合中已经存在的内容,则会引发异常。
经过一番挖掘,我发现我可以创建一个块并<<
像这样覆盖运算符:
has_many :albums, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Album" do
def <<(*items)
super(items) rescue ActiveRecord::RecordInvalid
end
end
has_many :artists, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Artist" do
def <<(*items)
super(items) rescue ActiveRecord::RecordInvalid
end
end
has_many :songs, -> { distinct }, through: :collectionitems, source: :collectable, source_type: "Song" do
def <<(*items)
super(items) rescue ActiveRecord::RecordInvalid
end
end
这让我更近了一步,因为现在异常已获救,并且记录很简单,如果它已经存在则不添加。
现在真正的问题:
假设我有一首歌曲的现有收藏项行:就像这样
Collection.first << Song.first
该歌曲已正确添加,因为它在集合中尚不存在。
现在,如果我尝试将 2 首或更多歌曲添加到同一个集合中并且其中一首歌曲已经存在(在本例中为歌曲 1),则添加失败。
Collection.first << Song.all
添加过程开始,但由于歌曲 1 已经存在,因此引发了异常,并且没有其他歌曲得到处理。
我想要的是让它简单地跳过第一首歌,因为它已经在收藏中了。有人可以在这里帮助我吗?