Rails没有通过连接模型运行has_many的destroy回调

我有两个AR模型和第三个has_many :through连接模型:

 class User < ActiveRecord::Base has_many :ratings has_many :movies, through: :ratings end class Movie < ActiveRecord::Base has_many :ratings has_many :users, through: :ratings end class Rating < ActiveRecord::Base belongs_to :user belongs_to :movie after_destroy do puts 'destroyed' end end 

有时,用户会想要直接放弃电影(不直接破坏评级)。 但是,当我这样做时:

 # puts user.movie_ids # => [1,2,3] user.movie_ids = [1, 2] 

尽管正确删除了连接记录, after_destroy调用rating的after_destroy回调。 如果我像这样修改我的用户模型:

 class User < ActiveRecord::Base has_many :ratings has_many :movies, through: :ratings, before_remove: proc { |u, m| Rating.where(movie: m, user: u).destroy_all } end 

一切正常,但这真的很难看,然后Rails尝试再次删除连接模型。

我怎样才能使用dependent: :destroy这种关联的策略,而不是dependent: :delete

回答我自己的问题,因为这对谷歌很难,答案是超级直观的(尽管我不知道理想的界面是什么)。

首先,这里详细描述了这种情况: https : //github.com/rails/rails/issues/7618 。 但是,具体的答案埋在页面的中间位置,问题已经关闭(即使它仍然是当前Rails版本中的一个问题)。

您可以通过将选项添加到has_many :through命令来为这些类型的连接模型析构指定dependent: :destroy ,如下所示:

 class User < ActiveRecord::Base has_many :ratings has_many :movies, through: :ratings, dependent: :destroy end 

这是违反直觉的,因为在正常情况下, dependent: :destroy会破坏特定关联的对象。

例如,如果我们有has_many :ratings, dependent: :destroy here,那么当该用户被销毁时,所有用户的评级都将被销毁。

我们当然不想破坏这里的特定电影对象,因为它们可能被其他用户/评级使用。 但是,在这种情况下,Rails神奇地知道我们想要破坏连接记录,而不是关联记录。