【问题标题】:Prevent orphaned objects, with has_many through associations, in Rails 3在 Rails 3 中使用 has_many 通过关联防止孤立对象
【发布时间】:2012-07-01 08:40:17
【问题描述】:

我有一个包含“成员”、“组”、“成员”和“用户”的模型。数据以树状结构组织,其中包含与其相关联的成员的组。没有任何组关联的成员被认为是孤立的,对应用程序没有用处。

当用户销毁组时,不应留下任何孤立成员。换句话说:当且仅当最后一个组关联被删除时,才应该销毁一个成员。最好这应该发生在单个事务中,但最重要的方面是孤立对象不会随着时间的推移在数据库中累积。

只应删除与用户关联的成员和组。其他用户拥有的组、成员和成员资格完全不受影响。 (有人可能会争辩说可以随时运行全局清理方法,但我想隔离破坏性操作以仅影响当前用户对象。)

我的问题:在 Rails 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

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 associations orphan


    【解决方案1】:

    我通过在 Membership 类中添加一个回调解决了这个问题,该回调会在成员资格被销毁时通知成员。如果成员对象不再具有任何组关联,则成员对象会自行销毁。

    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
    

    【讨论】:

    • 值得注意的是:这不适用于 has_and_belongs_to_many 关联,因为调用 after_destroy 的模型将不再具有 id 并且无法确定它曾经关联的对象与。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多