2012-07-01 3 views
4

"member", "group", "membership"및 "user"가있는 모델이 있습니다. 데이터는 연관된 멤버가있는 그룹과 함께 트리 구조로 구성됩니다. 단체 협의회가없는 회원은 고아로 간주되며 신청서에는 사용할 수 없습니다.레일스 3에서 연결을 통해 has_many가있는 고아 개체 방지

사용자가 그룹을 파괴 할 때 분리 된 회원이 없어야합니다. 즉, 마지막 그룹 연합이 제거 된 경우에만 회원을 파괴해야합니다. 이 작업은 단일 트랜잭션에서 수행하는 것이 가장 바람직하지만 시간이 지남에 따라 고아 개체가 데이터베이스에 누적되지 않는 것이 가장 중요합니다.

사용자와 관련된 구성원 및 그룹 만 제거해야합니다. 다른 사용자가 소유 한 그룹, 구성원 및 구성원은 전혀 영향을받지 않아야합니다. (전역 정리 방법은 언제든지 실행할 수 있다고 주장하지만, 현재 사용자 개체에만 영향을주는 파괴적인 작업을 격리하려고합니다.)이 질문에 유래 stackoverflow.com 질문 :이 기능을 구현하는 가장 효율적인 방법은 무엇입니까? 레일즈 3? 여기에 설명 된 단순화 된 모델로 표시된 현재 구현은 사용자가 수동으로 삭제하지 않거나 전체 사용자와 모든 데이터가 연쇄 삭제로 제거되지 않는 한 데이터베이스에서 멤버를 제거하지 않습니다.

class User < ActiveRecord::Base 
    has_many :groups, :foreign_key => 'owner_id', :dependent => :delete_all 
    has_many :members, :foreign_key => 'owner_id', :dependent => :destroy 
end 

class Member < ActiveRecord::Base 
    belongs_to :owner, :class_name => 'User'  
    has_many :memberships, :dependent => :destroy 
    has_many :groups, :through => :memberships 
end 

class Membership < ActiveRecord::Base 
    belongs_to :member 
    belongs_to :group 
end 

class Group < ActiveRecord::Base 
    belongs_to :owner, :class_name => 'User' 
    belongs_to :parent, :class_name => 'Group'  
    has_many :groups, :foreign_key => 'parent_id', :dependent => :destroy 
    has_many :memberships, :dependent => :destroy 
    has_many :members, :through => :memberships 
end 

답변

8

멤버쉽 클래스에서 콜백을 추가하여이 문제를 해결했습니다.이 콜백은 멤버십이 삭제되었을 때 멤버에게 알립니다. 그런 다음 구성원 개체는 더 이상 그룹 연결이없는 경우 자체를 파괴합니다.

class Membership < ActiveRecord::Base 
    belongs_to :member 
    belongs_to :group 

    after_destroy :notify_member 

    def notify_member 
    member.destroy_if_empty_groups 
    end 
end 

class Member < ActiveRecord::Base 
    belongs_to :owner, :class_name => 'User'  
    has_many :memberships, :dependent => :destroy 
    has_many :groups, :through => :memberships 

    def destroy_if_empty_groups 
    if groups.count == 0 
     self.destroy 
    end 
    end 
end 
+1

가치에 주목 :이 after_destroy'가 더 이상'id'가 없습니다 그것은과 연관 될하는 데 사용되는 개체를 판별 할 수 없습니다'호출 모델로'has_and_belongs_to_many' 협회 작동하지 않습니다. –