2

I have the following models:

User (id)
Project (id)
Permission (project_id, user_id)
Thread (project_id)
ThreadParticipation (thread_id, user_id)

So that's working nicely, problem is this. When a user leaves or is removed from a project, I need all their ThreadParticipation's for that project deleted.

Example, so if user(15), leaves project(3) by deleting the permission (user_id =>15, project_id => 3), I need rails to automatically then delete all related ThreadParticipation records (where ThreadParticipation through thread, belongs to project_id 3, and ThreadParticipation.user_id = 15.

I've tried this, but it's not doing anything:

has_many :thread_participations, :foreign_key => :user_id, :dependent => :destroy

Thoughts? Thanks

zetetic
  • 47,184
  • 10
  • 111
  • 119
AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012

3 Answers3

2

Are you maybe using delete instead of destroy? Using destroy will cause dependents to be removed while delete does not. see this

Community
  • 1
  • 1
Dty
  • 12,253
  • 6
  • 43
  • 61
1

In the Permission Model, do this:

before_destroy :delete_thread_participation

private
      def delete_thread_participation
         if self.threadparticipation 
           self.threadparticipation.delete_all "project_id ="+self.project_id+"and user_id="+self.user_id
         end
      end

This is considering you have relationships defined in the models

zeacuss
  • 2,563
  • 2
  • 28
  • 32
ajmartin
  • 2,379
  • 2
  • 26
  • 42
  • Thanks but I don't want this to happen when the user is deleted. I want the ThreadParticipations to be delete when the PERMISSION is deleted. The permission joins the user to the project. – AnApprentice Feb 14 '11 at 23:47
  • Edited. You can also have a cascading effect, by calling a function within `delete_thread_participation` like `self.user_id.some_function` or `self.project_id.some_function` – ajmartin Feb 15 '11 at 00:05
  • 3
    Wouldn't this be better as `delete_all(:project_id => project_id, :user_id => user_id)` – Ryan Bigg Feb 15 '11 at 00:22
  • @Ryan Bigg: Sure. Looks better. – ajmartin Feb 15 '11 at 00:59
  • @Ryan, how would that work, where would it go? Doesn't it need to stay which model to delete on? – AnApprentice Feb 15 '11 at 03:22
1

Try this:

class Project
  has_many :threads
  has_many :thread_participations, :through => :threads      
end

class Permission
  belongs_to :project

  after_destroy :destroy_thread_participations

  def destroy_thread_participations
    ThreadParticipation.delete_all(
      :id => project.thread_participations.find_all_by_user_id(user_id)
    )
  end
end

Use destroy_all instead of delete_all if you have *_destroy callbacks in the ThreadParticipation model. The delete_all call is faster than destroy_all as it performs deletion of multiple rows in one DB call and does not have the overhead of invoking the *_destroy callbacks.

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198