Search code examples
ruby-on-railssoft-delete

Soft delete with associations


I have three models:

User:

class User < ActiveRecord::Base
  has_many :posts, :dependent => :destroy
  scope :active, -> { where(deleted: false) }
end

Post:

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :comments, :dependent => :destroy

  scope :active, -> { where(deleted: false) }
end

Comment:

class Comment < ActiveRecord::Base
  belongs_to :post
  scope :active, -> { where(deleted: false) }
end

Now, I am doing soft delete for User and I have column named deleted in all three tables(User, Post, Comment)

User destroy method:

def destroy
  @user = user.find(params[:id])

  if @user.update_attributes(deleted: true)
    @user.posts.each do |post|
      post.comments.update_all(deleted: true)
    end

    @user.posts.update_all(deleted: true)
  end
end

The above implementation takes more time when no. of posts and comments are high and it also creates N+1 query problem..

Same as above I have implemented destroy method for Post, I don't know how to do it efficiently..

I don't want to use any kind of gem.

Please tell me a better way to do soft deletion for these kind of associations..


Solution

  • Do you really need to delete the posts? You could scope them out instead by including the user model when you retrieve them. Marking all descendants as deleted really isn't necessary when it can so easily be inferred from the parent.

    User:

    class User < ActiveRecord::Base
      has_many :posts, :dependent => :destroy
      scope :active, -> { where(deleted: false) }
    end
    

    Post:

    class Post < ActiveRecord::Base
      belongs_to :user
      has_many :comments, :dependent => :destroy
    
      scope :active, -> { joins(:user).merge(User.active) }
    end