ActiveRecord - 双向:依赖=> :破坏on_many< - > belongs_to association

时间:2014-09-24 16:46:44

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

在具有has_many belongs_to关联的rails 4应用程序中,应如何实现双向:dependent => :destroy功能?

ContactOrganisation为例。期望的行为如下:

  1. 销毁组织会破坏组织和所有相关联系人。
  2. 销毁与具有多个联系人的组织关联的联系人仅销毁该联系人。
  3. 销毁与组织关联的最后一个联系人会破坏联系人和相关组织。
  4. :dependent => :destroy上的has_many设置条件满足条件1和2,但不满足条件1。

    class Organisation < ActiveRecord::Base
      has_many :contacts, :dependent => :destroy
    end
    
    class Contact < ActiveRecord::Base
      belongs_to :organisation
    end
    

    :dependent => :destroy上设置belongs_to满足条件1和3,但不满足2。

    class Organisation < ActiveRecord::Base
      has_many :contacts
    end
    
    class Contact < ActiveRecord::Base
      belongs_to :organisation, :dependent => :destroy
    end
    

    实现这种行为的最简洁方法是什么?

1 个答案:

答案 0 :(得分:0)

我找到了一种解决方案,可以在不设置:dependent => :destroy的情况下实现所需的行为:

class Organisation < ActiveRecord::Base
  has_many :contacts

  def destroy
    self.contacts.delete_all if self.contacts.any?
    super
  end

class Contact < ActiveRecord::Base
  belongs_to :organisation

  after_destroy :cascade_destroy

  private

  def cascade_destroy
    self.organisation.destroy if self.organisation.contacts.empty?
  end
end

而不是覆盖Organisation#destroy我试过在:dependent => :destroy关联上设置has_many :contacts,但是我相信这创建了一个无限循环,因为它导致应用程序抛出'堆栈级别太深'错误。

调用self.contacts.delete_all似乎可以避免这个问题,但我不知道为什么。