Viblo CTF
+1

Soft delete với gem paranoia

Soft delete là cách đơn giản để bảo vệ an toàn cho dữ liệu của hệ thống. Bằng việc không xóa hoàn toàn record trong Database, mà chỉ đưa nó về một trạng thái nào đó được quy ước là đã xóa, tức không còn tồn tại trong các câu truy vấn thông thường. Trước khi đi vào tìm hiểu cách sử dụng gem paranoia để thực hiện soft delete, chúng ta hãy cân nhắc một số điểm sau trước khi quyết định sử dụng soft delete trong hệ thống của mình.

  • Nếu thực hiện hard delete, tức xóa hoàn toàn record trong database bằng câu truy vấn DELETE quen thuộc, rất đơn giản chúng ta đã xóa hoàn toàn các dữ liệu cần loại bỏ. Không còn dữ liệu dư thừa trong hệ thống, nó sẽ chạy nhanh hơn; nhưng cùng với điều đó là chúng ta không thể khôi phục lại dữ liệu đã xóa, dữ liệu đó đã mất vĩnh viễn nếu bạn không có bản backup nào cho nó.
  • Thay vì dùng hard delete, chúng ta sử dụng soft delete để giữ lại các bản ghi đã bị loại bỏ. Có một vấn đề xảy ra: chúng ta đã không xóa bất kỳ của relation của bản ghi đã xóa, mà có thể là những thứ sẽ gây ra lỗi nghiêm trọng mà chúng ta không lường đến. Để khắc phục việc này, bạn sẽ phải chuyển việc xử lý những rắc rối đó sang cho ứng dụng của mình, mà chưa chắc rằng các cách xử lý đó sẽ khắc phục hết những rắc rối do những record relation đó sinh ra. Cùng với đó là việc các query không được xóa sẽ làm cho hệ thống của chúng ta nặng nề hơn, dẫn đến việc thực hiện các query khác cũng chậm hơn.
  1. Tìm hiểu cách thực hiện của gem paranoia

    Paranoia thực hiện soft delete bằng cách thêm 1 column deleted_at với giá trị mặc định là nil trong table mà chúng ta cần soft delete tại đó. Như vậy khi gọi hàm destroy trong ActiveRecord object của model đó, record đó sẽ không bị xóa đi mà sẽ được update trường deleted_at với giá trị được quy định sẵn. Nếu record có chứa liên kết has_many, các record có tên trong quan hệ has_many đều cũng sẽ được soft delete.

    Để cài đặt gem paranoia, ta thêm tên gem vào Gemfile:

    # Với Rails 3:
    gem "paranoia", "~> 1.0"
    # Với Rails 4:
    gem "paranoia", "~> 2.0"
    # Với Rails 5:
    gem "paranoia", "~> 2.2.0.pre"
    # Hoặc:
    gem "paranoia", github: "rubysherpas/paranoia", branch: "rails3"
    gem "paranoia", github: "rubysherpas/paranoia", branch: "rails4"
    gem "paranoia", github: "rubysherpas/paranoia", branch: "rails5"

Sau đó chạy bundle ínstall để cài đặt.

Chạy migrate để thêm column deleted_at vào table:

    bin/rails generate migration AddDeletedAtToClient deleted_at:datetime:index
    # Client là tên table cần soft delete

Thêm acts_as_paranoid vào model để thực hiện soft delete với ActiveRecord

  1. Cách sử dụng gem

Sau khi hoàn tất việc cài đặt, khi gọi delete sẽ update gía trị cho trường deleted_at:

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

Để thực hiện việc xóa hoàn toàn record, chúng ta chạy lệnh really_destroy!:

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

Để truy vấn tất cả các record đã bị xóa bởi soft delete:

Client.only_deleted

Để truy vấn tất cả các record đang tồn tại trong database, bao gồm đã xóa và chưa xóa:

Client.with_deleted

Để kiểm tra xem record đó đã được soft delete hay chưa:

client.paranoia_destroyed?
# or
client.deleted?

Để khôi phục record đã bị soft delete:

Client.restore(id)
# or
client.restore
# or
Client.restore([id1, id2, ..., idN])

Nếu muốn khôi phục cả những record có quan hệ dependently destroyed:

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

All Rights Reserved