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神奇地知道我们想要破坏连接记录,而不是关联记录。