带关联的软删除

时间:2016-07-06 12:41:22

标签: ruby-on-rails soft-delete

我有三种模式:

用户:

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

发表:

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

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

注释:

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

现在,我正在对User进行软删除,并且我在所有三个表中都有deletedUser, Post, Comment

用户销毁方法:

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

上述实施需要更多时间。帖子和评论很高,它也会产生N + 1查询问题..

与上面相同,我为destroy实施了Post方法,我不知道如何有效地做到这一点。

我不想使用任何一种宝石。

请告诉我一种更好的方法来对这些关联进行软删除..

2 个答案:

答案 0 :(得分:1)

你真的需要删除这些帖子吗?您可以通过在检索用户模型时包含用户模型来取代它们。当从父母那里很容易地推断出将所有后代标记为已删除时,确实没有必要。

用户:

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

发表:

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

  scope :active, -> { joins(:user).merge(User.active) }
end

答案 1 :(得分:1)

如果完全是关于效率(去除N + 1),我会做以下事情。我也是&#34;脂肪模型和瘦身控制者&#34;所以我会把你的逻辑从控制器转移到用户模型:

class User < ActiveRecord::Base
  has_many :posts, dependent: :destroy
  has_many :comments, through: :posts

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

  after_save :delete_posts_and_comments, if: :delete_posts?

  private

    def delete_posts?
      deleted_changed? && deleted
    end

    def delete_posts_and_comments
      posts.update_all(deleted: true)
      comments.update_all(deleted: true)
    end
end

当然,您可以使用相同的模式撤消删除。

请注意! update_all不会触发更新实体的任何验证或回调。