4

「メンバー」、「グループ」、「メンバーシップ」、「ユーザー」のモデルがあります。データは、メンバーが関連付けられているグループを持つツリー構造で編成されています。グループの関連付けがないメンバーは孤立していると見なされ、アプリケーションには使用できません。

ユーザーがグループを破棄するときに、孤立したメンバーを残してはなりません。つまり、最後のグループの関連付けが削除された場合にのみ、メンバーを破棄する必要があります。これは単一のトランザクションで発生することが望ましいですが、最も重要な側面は、孤立したオブジェクトが時間の経過とともにデータベースに蓄積されないことです。

ユーザーに関連付けられているメンバーとグループのみを削除する必要があります。他のユーザーが所有するグループ、メンバー、およびメンバーシップは、まったく影響を受けません。(グローバルクリーンアップメソッドはいつでも実行できると主張する人もいるかもしれませんが、破壊的な操作を分離して、現在のユーザーオブジェクトにのみ影響を与えたいと思います。)

私の質問: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
4

1 に答える 1

10

メンバーシップが破棄されたときにメンバーに通知するコールバックを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
于 2012-07-27T19:46:05.823 に答える