ruby-on-rails - Rails没有通过join模型运行has_many的destroy回调

标签 ruby-on-rails ruby-on-rails-4 rails-activerecord

我有两个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

最佳答案

回答我自己的问题,因为这对Google来说很困难,而且答案是违反直觉的(尽管我不知道理想的界面是什么)。

首先,在这里对情况进行详细描述: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神奇地知道,在这种情况下,我们要销毁联接记录,而不是销毁关联记录。

关于ruby-on-rails - Rails没有通过join模型运行has_many的destroy回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30629680/

相关文章:

ruby-on-rails - Mac 终端重新启动后无法运行大多数命令

ruby-on-rails - Rails/Ruby : Any way to shorten the stack traces?

html - Rails 使用第三方生成的 html 的最佳方式

ruby-on-rails - ActiveRecord 查询 : Get Distinct Users from Posts in Category

ruby-on-rails - 模型 belongs_to eiher/or more than one models

ruby-on-rails - remove_reference 和 add_reference 的向下迁移报告没有外键

ruby-on-rails - 事件记录迁移 Rails 4 中的 has_many、belongs_to 关系

ruby-on-rails - Rails 部分表验证

ruby-on-rails - rails : how to exclude one item from an "each" method

ruby-on-rails - 在事件管理 Rails 4 中的显示页面上更改删除操作的确认消息