我有两个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
回调。如果我像这样修改我的用户模型:
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
?
答案 0 :(得分:11)
回答我自己的问题,因为这对谷歌来说很难,答案是超级直观的(虽然我不知道理想界面会是什么)。
首先,这里详细描述了这种情况:https://github.com/rails/rails/issues/7618。但是,具体的答案埋在页面的中间位置,问题已经关闭(即使它仍然是当前Rails版本中的一个问题)。
您可以通过向dependent: :destroy
命令添加选项为这些类型的连接模型析构指定has_many :through
,如下所示:
class User < ActiveRecord::Base
has_many :ratings
has_many :movies,
through: :ratings,
dependent: :destroy
end
这是违反直觉的,因为在正常情况下,dependent: :destroy
会破坏该特定关联的对象。
例如,如果我们在此处has_many :ratings, dependent: :destroy
,那么当该用户被销毁时,所有用户的评级都将被销毁。
我们当然不想破坏这里的特定电影对象,因为它们可能被其他用户/评级使用。但是,在这种情况下,Rails神奇地知道我们想要破坏连接记录,而不是关联记录。