ruby-on-rails – 如何隐藏记录,而不是删除它们(从头开始软删除)

让我们保持简单.假设我有一个用户模型和一个邮政模型:
class User < ActiveRecord::Base
    # id:integer name:string deleted:boolean

    has_many :posts       
end

class Post < ActiveRecord::Base
    # id:integer user_id:integer content:string deleted:boolean

    belongs_to :user
end

现在,我们来说一个管理员想“删除”(隐藏)一个帖子.所以基本上他通过系统把一个帖子的已删除属性设置为1.我该如何在视图中显示这个帖子?我应该在这个帖子上创建一个虚拟属性

class Post < ActiveRecord::Base
    # id:integer user_id:integer content:string deleted:boolean

    belongs_to :user

    def administrated_content
       if !self.deleted
          self.content
       else
          "This post has been removed"
       end
    end
end

虽然这样会起作用,但我想在大量的模型中实现上述,我不禁感觉到将上述比较文字粘贴到我所有的模型中都可以是DRYER.很多烘干机.

我也认为,在我的应用程序中,每一个删除的模型中都删除一个列,也有点麻烦.我觉得我应该有一个’状态’表.你对此有何想法?

class State
    #id:integer #deleted:boolean #deleted_by:integer

    belongs_to :user
    belongs_to :post
end

然后在比较器中查询self.state.deleted?这需要一个多态表吗?我只尝试过多态,我无法让它工作. (这是一个非常复杂的自我参照模式,心灵).这仍然没有解决在我的模型中有一个非常非常相似的类方法以检查在显示内容之前是否删除实例的问题.

在deleted_by属性中,我正在考虑将管理员的ID删除.但是管理员取消删除帖子怎么办?也许我应该有一个edited_by id.

如何设置依赖关系::用户和他的帖子之间的销毁类型关系?因为现在我想这样做:依赖::set_deleted_to_0,我不知道该怎么做.

此外,我们不仅仅希望将帖子的已删除属性设置为1,因为我们实际上想要更改我们的administrationated_content发出的消息.我们现在想要说的是,由于其用户已被删除,此帖子已被删除.我相信我可以跳进去做一些奇怪的事情,但我想从一开始就做好准备.

我也尽量避免宝石,因为我觉得我错过了学习.

解决方法

在这种情况下,我通常使用一个名为deleted_at的字段:
class Post < ActiveRecord::Base
  scope :not_deleted,lambda { where(deleted_at: nil) }
  scope :deleted,lambda { where("#{self.table_name}.deleted_at IS NOT NULL") }

  def destroy
    self.update_attributes(deleted_at: DateTime.current)
  end

  def delete
    destroy
  end

  def deleted?
    self.deleted_at.present?
  end
  # ...

分享多种机型之间的功能

=>扩展它吧!

# lib/extensions/act_as_fake_deletable.rb
module ActAsFakeDeletable
  # override the model actions
  def delete
    self.update_attributes(deleted_at: DateTime.current)
  end
  def destroy
    self.update_attributes(deleted_at: DateTime.current)
  end

  # define new scopes
  def self.included(base)
    base.class_eval do
      scope :deleted,where('deleted_at IS NOT NULL')
      scope :not_deleted,where('deleted_at IS NULL')

      scope :destroyed,where('deleted_at IS NOT NULL')
      scope :not_destroyed,where('deleted_at IS NULL')
    end
  end
end

class ActiveRecord::Base
  def self.act_as_fake_deletable(options = {})
    alias_method :destroy!,:destroy
    alias_method :delete!,:delete
    include ActAsFakeDeletable

    options = { field_to_hide: :content,message_to_show_instead: "This content has been deleted" }.merge!(options)

    define_method options[:field_to_hide].to_sym do
      return options[:message_to_show_instead] if self.deleted_at.present?
      self.read_attribute options[:field_to_hide].to_sym
    end
  end
end

用法

class Post < ActiveRecord::Base
  act_as_fake_deletable

覆盖认值:

class Book < ActiveRecord::Base
  act_as_fake_deletable field_to_hide: :title,message_to_show_instead: "This book has been deleted man,sorry!"

繁荣!完成.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...