问题描述
我有两个 AR 模型和第三个 has_many :through
连接模型,如下所示:
I have two AR models and a third has_many :through
join model like this:
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
有时,用户会想要直接删除电影(而不直接破坏评级).但是,当我这样做时:
Occasionally, a user will want to drop a movie directly (without directly destroying the rating). However, when I do:
# puts user.movie_ids
# => [1,2,3]
user.movie_ids = [1, 2]
评级的 after_destroy
回调不会被调用,尽管连接记录已被适当删除.如果我像这样修改我的用户模型:
the rating's after_destroy
callback isn't called, although the join record is deleted appropriately. If I modify my user model like this:
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 再次尝试删除连接模型.
Everything works fine, but this is really ugly, and Rails then tries to delete the join model a second time.
我如何为这个关联使用 dependent: :destroy
策略,而不是 dependent: :delete
?
How can I use a dependent: :destroy
strategy for this association, rather than dependent: :delete
?
推荐答案
回答我自己的问题,因为这对 Google 来说很难,而且答案超级反直觉(虽然我不知道理想的界面是什么)).
Answering my own question, since this was difficult to Google, and the answer is super counter-intuitive (although I don't know what the ideal interface would be).
首先,这里详细描述了情况:https://github.com/rails/rails/issues/7618.然而,具体的答案被埋在了页面的一半左右,问题被关闭了(尽管它在当前的 Rails 版本中仍然是一个问题).
First, the situation is described thoroughly here: https://github.com/rails/rails/issues/7618. However, the specific answer is buried about halfway down the page, and the issue was closed (even though it is still an issue in current Rails versions).
您可以为这些类型的连接模型销毁指定 dependent: :destroy
,方法是在 has_many :through
命令中添加选项,如下所示:
You can specify dependent: :destroy
for these types of join model destructions, by adding the option to the has_many :through
command, like this:
class User < ActiveRecord::Base
has_many :ratings
has_many :movies,
through: :ratings,
dependent: :destroy
end
这是违反直觉的,因为在正常情况下,dependent::destroy
会破坏特定关联的对象.
This is counter-intuitive because in normal cases, dependent: :destroy
will destroy that specific association's object(s).
例如,如果我们在这里有 has_many :ratings,dependent: :destroy
,那么当该用户被销毁时,该用户的所有评分都将被销毁.
For example, if we had has_many :ratings, dependent: :destroy
here, all of a user's ratings would be destroyed when that user was destroyed.
我们当然不想在这里销毁特定的电影对象,因为其他用户/评级可能正在使用它们.然而,在这种情况下,Rails 神奇地知道我们要销毁连接记录,而不是关联记录.
We certainly don't want to destroy the specific movie objects here, because they may be in use by other users/ratings. However, Rails magically knows that we want to destroy the join record, not the association record, in this case.
这篇关于Rails 没有通过连接模型为 has_many 运行销毁回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!