paranoia, 用于 Rails 3 & 4的acts_as_paranoid

分享于 

13分钟阅读

GitHub

  繁體 雙語
acts_as_soft_deletable for Rails 3 & 4
  • 源代码名称:paranoia
  • 源代码网址:http://www.github.com/rubysherpas/paranoia
  • paranoia源代码文档
  • paranoia源代码下载
  • Git URL:
    git://www.github.com/rubysherpas/paranoia.git
    Git Clone代码到本地:
    git clone http://www.github.com/rubysherpas/paranoia
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/rubysherpas/paranoia
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    

    通知:

    paranoia 有一些令人惊奇的行为( 像重写activerecord和 destroydelete ),并且不推荐新项目。 有关详细信息,请参阅的 discard 自述文件。

    偏执将继续接受 Bug 修复并支持 Rails的新版本,但不接受新的特性。

    偏执

    Paranoia是 acts_as_paranoid的一个实现,它使用大量的。多的代码来实现 Rails 3/4/5,。

    应用程序使用偏执时,在ActiveRecord对象上调用 destroy 实际上不会破坏数据库记录,但是只会隐藏数据库记录,而不会破坏它。 通过将一个 deleted_at 字段设置为当前的时间,Paranoia Paranoia Paranoia,并通过对模型中的所有查询只包含不包含字段的记录来隐藏。

    如果你想实际销毁一个对象,你可以调用 really_destroy。! 这也会破坏你的所有 dependent: :destroy 记录,所以请在使用时把这个方法用在脸上。

    如果记录定义了 has_many 关联,那么这些关联将在它们上设置 dependent: :destroy,如果设置了 acts_as_paranoid,则将调用正常消除。 通过关联回调 Destroying,用于澄清示例。

    开始视频

    偏执 gem GoRails #41的设置和基本用法

    安装&用法

    对于 Rails 3,请使用Paranoia的版本 1:

    gem "paranoia", "~> 1.0"

    对于 Rails 4和 5,请使用 Paranoia ( Rails 5需要 2.2或者 GREATER )的版本 2:

    gem "paranoia", "~> 2.2"

    当然,你也可以从以下示例之一从GitHub安装这里组件:

    gem "paranoia", github:"rubysherpas/paranoia", branch:"rails3"gem "paranoia", github:"rubysherpas/paranoia", branch:"rails4"gem "paranoia", github:"rubysherpas/paranoia", branch:"rails5"

    然后运行:

    bundle install

    更新与 bundle update paranoia 一样简单。

    为所需模型运行迁移

    运行:

    bin/rails generate migration AddDeletedAtToClients deleted_at:datetime:index

    现在你有了一个迁移

    classAddDeletedAtToClients <ActiveRecord::Migrationdefchange add_column :clients, :deleted_at, :datetime add_index :clients, :deleted_atendend

    用法

    你的模型中的:
    classClient <ActiveRecord::Base acts_as_paranoid
     #.. .end

    Hey,它在那里调用 destroy 将设置 deleted_at 列: !

    >> client.deleted_at# => nil>> client.destroy# => client>> client.deleted_at# => [current timestamp]

    如果你真的想让它消失,请拨打 really_destroy:!

    >> client.deleted_at# => nil>> client.really_destroy!# => client

    如果要使用 deleted_at 以外的列,可以将它的作为选项传递:

    classClient <ActiveRecord::Base acts_as_paranoid column::destroyed_at. . .end

    如果要跳过添加默认作用域:

    classClient <ActiveRecord::Base acts_as_paranoid without_default_scope:true. . .end

    如果要访问软删除的关联,请重写getter方法:

    defproductProduct.unscoped { super }end

    如果要包含关联的软删除对象,可以使用( un ) 作用域:

    classPerson <ActiveRecord::Base belongs_to :group, -> { with_deleted }endPerson.includes(:group).all

    如果要查找所有记录,即使是删除的记录:

    Client.with_deleted

    如果要排除已经删除的记录,则在无法使用 default_scope ( 比如 ) 时。 使用without_default_scope时:

    Client.without_deleted

    如果你只想查找已经删除的记录:

    Client.only_deleted

    如果你要检查记录是否已经被软删除:

    client.paranoia_destroyed?# orclient.deleted?

    如果要还原记录:

    Client.restore(id)# orclient.restore

    如果要恢复全部记录,请执行以下操作:

    Client.restore([id1, id2,.. ., idN])

    如果要还原记录及其独立的关联记录,请执行下列操作:

    Client.restore(id, :recursive => true)# orclient.restore(:recursive => true)

    如果要还原记录,并且仅在被删除的相关记录在它的依赖的对象的2分钟内被删除:

    Client.restore(id, :recursive => true. :recovery_window => 2.minutes)# orclient.restore(:recursive => true, :recovery_window => 2.minutes)

    请注意,默认情况下,of不会阻止软毁坏对象与另一个模型的另一个对象相关联。 如果需要这里功能,则提供 Rails 验证程序:

    validates :some_assocation, association_not_soft_destroyed:true

    这里验证器确保 some_assocation 不是软销毁的。 如果对象被软破坏,主对象呈现无效,并添加验证错误。

    有关更多信息,请查看测试。

    关于索引:

    注意,应该调整所有索引,使它的与以前一样快。 比如,

    add_index :clients, :group_idadd_index :clients, [:group_id, :other_id]

    应替换为

    add_index :clients, :group_id, where:"deleted_at IS NULL"add_index :clients, [:group_id, :other_id], where:"deleted_at IS NULL"

    当然,对于经常使用 with_deleted 或者 only_deleted的索引来说,这是不必要的。

    唯一索引

    因为标准SQL中的空!= 空,我们不能简单地在deleted_at列上创建一个唯一的索引。

    如果数据库支持,好的选择包括部分索引( 上方上方) 和计算列的索引。 E.g.

    add_index :clients, [:group_id, 'COALESCE(deleted_at, false)'], unique:true

    如果没有,另一个选择是创建一个独立的列,以便为强制执行唯一性而维护 deleted_at。 为此,偏执利用两种方法来进行它的破坏和恢复操作: paranoia_restore_attributes和 paranoia_destroy_attributes。

    add_column :clients, :active, :booleanadd_index :clients, [:group_id, :active], unique:trueclassClient <ActiveRecord::Base# optionally have paranoia make use of your unique column, so that# your lookups will benefit from the unique index acts_as_paranoid column::active, sentinel_value:truedefparanoia_restore_attributes {
     deleted_at:nil,
     active:true }
     enddefparanoia_destroy_attributes {
     deleted_at: current_time_from_proper_timezone,
     active:nil }
     endend
    通过关联回调进行破坏

    处理 dependent: :destroy 关联和 acts_as_paranoid 时,务必记住,无论在父模型上调用什么方法,都要在子模型上调用。 例如给定关联的两个模型都定义了 acts_as_paranoid:

    classClient <ActiveRecord::Base acts_as_paranoid
     has_many :emails, dependent::destroyendclassEmail <ActiveRecord::Base acts_as_paranoid
     belongs_to :clientend

    在父 client 上调用 destroy 时,它将调用它的所有关联的子级 emails 上的destroy:

    >> client.emails.count# => 5>> client.destroy# => client>> client.deleted_at# => [current timestamp]>>Email.where(client_id: client.id).count# => 0>>Email.with_deleted.where(client_id: client.id).count# => 5

    同样,在父 client 上调用 really_destroy 时,每个子 email 也将具有 really_destroy:!

    >> client.emails.count# => 5>> client.id# => 12345>> client.really_destroy!# => client>>Client.find 12345# => ActiveRecord::RecordNotFound>>Email.with_deleted.where(client_id: client.id).count# => 0

    但是,如果子模型 email 没有 acts_as_paranoid 设置,则在父 client 上调用 destroy 也将在每个子 email 上调用 destroy,从而实际销毁它们:

    classClient <ActiveRecord::Base acts_as_paranoid
     has_many :emails, dependent::destroyendclassEmail <ActiveRecord::Base belongs_to :clientend>> client.emails.count# => 5>> client.destroy# => client>>Email.where(client_id: client.id).count# => 0>>Email.with_deleted.where(client_id: client.id).count# => NoMethodError: undefined method `with_deleted' for #<Class:0x0123456>

    作为偏执迁移

    你可以替换旧的acts_as_paranoid 方法,如下所示:

    旧语法新语法
    find_with_deleted(:all)Client.with_deleted
    find_with_deleted(:first)Client.with_deleted.first
    find_with_deleted(id)Client.with_deleted.find(id)

    acts_as_paranoid 中的recover 方法运行 update 回调。 paranoia方法的restore 不执行这里操作。

    回调

    is提供多个回调当记录被完全删除时,当记录被标记为已经删除和 real_destroy 时,它会触发 destroy 回调。 它也调用 restore 回调,当记录通过偏执恢复时

    例如如果你想在某些搜索引擎中索引你的记录,你可以这样做:

    classProduct <ActiveRecord::Base acts_as_paranoid
     after_destroy :update_document_in_search_engine after_restore :update_document_in_search_engine after_real_destroy :remove_document_from_search_engineend

    你可以像以前的Rails 回调一样使用这些事件。

    许可证

    这个 gem 是在MIT许可下发布的。


    rails  act  
    相关文章