Question

I have two models, User and Image.

class User < ActiveRecord::Base
  has_many :images,:order => "created_at DESC", :dependent => :destroy, :conditions => "archive = 0"

  def destroy
    self.archive = 1
    self.deleted_at = Time.now
    self.save
  end 
end 


class Image < ActiveRecord::Base
 belongs_to :user , :counter_cache => true

 def destroy
  self.archive = 1
  self.deleted_at = Time.now
  self.save
 end   
end

Now if you see above code, I am overriding destroy call in a model. Not when user is deleting his account I want to trigger dependent => destroy call back so that i triggers destroy for Image.

PS: I dont want to use act_as_paranoid or some other plugins. I need to trigger dependent=> destroy as I have a very deep complex mapping something like:

User has_many images, has_many comments, has_many likes, has_many activities and some more 9 types of mappings and again deep maping etc.

Was it helpful?

Solution

Perhaps to make things a bit easier, you could encapsulate the behavior of both the archiving model and archivable models in modules:

module Archivable
  def archive!
    self.archive = 1
    self.deleted_at = Time.now
    self.save
  end
end

module Archiver
  def destroy
    self.archive = 1
    self.deleted_at = Time.now
    archive_models!
    self.save
    freeze
  end

  def archive_models!
    archivable_models.each do |model|
      model_name = model.name.pluralize.downcase.to_s
      self.send(model_name).each { |m| m.archive! }
    end
  end

  def archivable_models
    ActiveRecord::Base.send(:subclasses).select { |m| m.method_defined?(:archive!) }
  end
end

class Image < ActiveRecord::Base
  include Archivable
  belongs_to :user, :counter_cache => true
end

class User < ActiveRecord::Base
  include Archiver 
  has_many :images,:order => "created_at DESC", :conditions => "archive = 0", :dependent => :destroy
  attr_accessible :name
end

This is a pretty hack-ish implementation, but it works. If you add a Comment model as described in your post, you'd simply add the has_many statement to User and include Archivable in the Comment model:

class User < ActiveRecord::Base
  include Archiver 
  has_many :images,:order => "created_at DESC", :conditions => "archive = 0", :dependent => :destroy
  has_many :comments,:order => "created_at DESC", :conditions => "archive = 0", :dependent => :destroy
  attr_accessible :name
end


class Comment < ActiveRecord::Base
  include Archivable
  belongs_to :user, :counter_cache => true
end

OTHER TIPS

You just need emulate the dependent destroy.

In your destroy method call all destroy method of your Image

class User < ActiveRecord::Base
  has_many :images,:order => "created_at DESC", :dependent => :destroy, :conditions => "archive = 0"

  def destroy
    self.archive = 1
    self.deleted_at = Time.now
    self.save
    self.images.each(&:destroy)
  end 
end 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top