设置集合时,ActiveRecord has_many关联不会调用after_destroy

时间:2012-07-05 08:18:03

标签: ruby-on-rails has-many

3个模特:用户,电影,喜欢

User has_many :likes
User has_many :movies, through: :likes

此代码:

user.movies = [ m1, m2, m3 ]

为与用户和m1 / m2 / m3相关的新Like#after_create记录调用Like。然后,这段代码:

user.movies = [ m3, m4 ]

不会针对将用户与m1 / m2相关联的Like#after_destroy记录调用Like,但会针对与m4的新关系调用Like#after_create

movies集合可以手动设置,也可以使用包含user[movie_ids]个复选框的表单设置,然后

user.update_attributes(params[:user])
  1. 设置集合的Rails方法是什么?
  2. 如何强制它调用after_destroy?
  3. 更新

    正如@jdoe从文档中引用的那样,在分配新集合或从集合中删除时(user.movies.delete(m1))无法实现。唯一的方法是在用户模型上使用before_remove / after_remove回调(如果是多态关系 - 任何其他模型),使用has_many定义:

    has_many :movies, through: :likes, before_remove: :before_like_destroy, after_remove: after_like_destroy
    
    def before_like_destroy(movie)
      like = self.likes.where(movie_id: movie)
      # trigger the after_destroy on like
      like.trigger_before_destroy # to be implemented on like, should call what the original callbacks contained
    end
    
    def after_like_destroy(movie)
      # no way to get Like object here because it was already removed, need to remember it on the before_destroy somehow
    end
    

    无法理解它背后的逻辑。它使关系模型的回调完全无用。如果在after_create上发生了某些事情,则无法在after_destroy中撤消,因为更好的做法是将逻辑放在一起之前和之后,而不是单独放置,这会使所有回调都无效。

    想想我会写一个自动化的宝石。

2 个答案:

答案 0 :(得分:3)

根据文件:

  

collection = objects

     

通过删除和添加对象来替换集合内容   适当。如果:through选项是连接中的真回调   模型被触发除了销毁回调,因为删除是   直接

答案 1 :(得分:0)

如果你将like :: destroy添加到like和movie关联中,它会调用after_destroy回调