【问题标题】:Howto use callbacks in a has_many through association?如何通过关联在 has_many 中使用回调?
【发布时间】:2012-05-22 19:06:26
【问题描述】:

我有一个通过 has_many 关联到项目模型的任务模型,并且需要在通过关联删除/插入之前操作数据。

由于“Automatic deletion of join models is direct, no destroy callbacks are triggered.”我不能为此使用回调。

在任务中,我需要所有 project_ids 来计算保存任务后项目的值。 如何通过关联禁用删除或更改删除以销毁 has_many? 这个问题的最佳做法是什么?

class Task
  has_many :project_tasks
  has_many :projects, :through => :project_tasks

class ProjectTask
  belongs_to :project
  belongs_to :task

class Project
  has_many :project_tasks
  has_many :tasks, :through => :project_tasks

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 callback has-many-through


    【解决方案1】:

    似乎我必须使用associations callbacksbefore_addafter_addbefore_removeafter_remove

    class Task
      has_many :project_tasks
      has_many :projects, :through => :project_tasks, 
                          :before_remove => :my_before_remove, 
                          :after_remove => :my_after_remove
      protected
    
      def my_before_remove(obj)
        ...
      end
    
      def my_after_remove(obj)
        ...
      end
    end   
    

    【讨论】:

      【解决方案2】:

      这就是我所做的

      在模型中:

      class Body < ActiveRecord::Base
        has_many :hands, dependent: destroy
        has_many :fingers, through: :hands, after_remove: :touch_self
      end
      

      在我的 Lib 文件夹中:

      module ActiveRecord
        class Base
        private
          def touch_self(obj)
            obj.touch && self.touch
          end
        end
      end
      

      【讨论】:

        【解决方案3】:

        更新加入模型关联,Rails 添加和删除集合上的记录。要删除记录,Rails 使用delete 方法,这个方法不会调用任何destroy callback

        您可以强制 Rails 在删除记录时调用 destroy 而不是 delete。 为此,请安装 gem replace_with_destroy 并将选项 replace_with_destroy: true 传递给 has_many 关联。

        class Task
          has_many :project_tasks
          has_many :projects, :through => :project_tasks,
                    replace_with_destroy: true
          ...
        end
        
        class ProjectTask
          belongs_to :project
          belongs_to :task
        
          # any destroy callback in this model will be executed
          #...
        
        end
        
        class Project
          ...
        end
        

        这样,您可以确保 Rails 调用所有 destroy callbacks。如果您使用的是paranoia,这可能非常有用。

        【讨论】:

          【解决方案4】:

          似乎将dependent: :destroy 添加到has_many :through 关系会破坏连接模型(而不是删除)。这是因为CollectionAssociation#delete 内部引用:dependent 选项来确定是否应该删除或销毁传递的记录。

          所以在你的情况下,

          class Task
            has_many :project_tasks
            has_many :projects, :through => :project_tasks, :dependent => :destroy
          end
          

          应该可以。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-04
            相关资源
            最近更新 更多