ActiveRecord中实现软删除
来源:互联网 发布:php 面向对象 太烂 编辑:程序博客网 时间:2024/05/21 07:52
软删除即不真正删除数据库中的数据,数据是可以恢复的,只是对用户来讲是不可见的。软删除在实际应用中很广泛,除了一般的论坛应用,在微博和微信之类的应用中也随处可见。为什么要有软删除而不是直接删除呢?个人认为主要有两个方面的原因:一是数据本身就是有价值或有潜在价值的东西,二是和数据本身关联的其他数据有很多,比如文章的评论,如果直接删除了文章,那么评论也会随之被删除,某些用户可能并不希望这样。因此,软删除可以很好的解决这个问题。
我想在应用中实现软删除也主要是因为文章和评论不宜直接从数据库中删除,如果一篇文章被作者删除,应用需要告诉收藏这篇文章的用户和评论这篇文章的用户:这篇文章已经被作者删除了;当3楼的评论被作者删除,应用也需要告诉@3楼的其他用户:3楼的评论已经被作者删除。这可以提高用户的体验。
一开始,我对如何实现软删除是没有什么好的思路的,我也知道会有很多的 gem 包可以实现这个功能,但是我还是想手动实现软删除的功能。通过求助 stackoverflow,我得到了一些思路:
1) 为数据库添加一个新字段来表示记录是否被软删除 2) 使用 ActiveSupport::Concern
第一个思路很好理解,即在数据库表中添加一个新字段做标志位,如果需要软删除,则设置为1,否则设置为0,也可以填充其他内容。
#app/models/comment.rbclass Comment ... field :deleted_at, type: DataTime default_scope ->{ where(deleted_at: nil) } ... def soft_destroy self.update_attributes(deleted_at: Time.now) end ...end
此处设置 deleted_at 为标志位,如果是软删除则设置 deleted_at 的时间为当前时间。设置默认的 scope 是为了在每次查询的时候过滤掉软删除的记录。soft_destroy 是用来取代 destroy 方法。这样一来就基本上实现了软删除的功能,看起来还是比较简单的,对吧
但是此处存在一个问题:除了 Comment model 需要添加软删除的功能,Article model 也需要,如果简单的拷贝代码到 。Article model 当中,那就违反了 Rails DRY 原则。我们需要把软删除的功能封装成一个 module,可以让不同的 model 有选择性的调用,此处就要用到ActiveSupport::Concern
。
ActiveSupport::Concern
在 models 的 concerns 目录新添加一个文件 soft_delete.rb,将软删除的功能封装到其中的 SoftDelete module 当中。
#app/models/concerns/soft_delete.rbmodule SoftDelete extend ActiveSupport::Concern included do field :deleted_at, type: DateTime default_scope ->{ where(deleted_at: nil) } def soft_destroy self.update_attributes(deleted_at: Time.now) end endend
在 Comment model中引用 SoftDelete module:
#app/models/comment.rbclass Comment include Mongoid::Document include SoftDelete ...end
将 comments_controller.rb
中的 destroy 方法替换为 soft_destroy 方法:
#app/controllers/comments_controller.rbdef destroy @comment.soft_destroy ...end
修改对应的视图文件,根据 deleted_at 字段判断评论是否被删除:
#app/views/comments/_show_html.erb<% @article.comments.unscoped.each_with_index do |comment, index| %> <ul class="list-group"> <li class="list-group-item"> <% if comment.deleted_at %> <h6 class="text-center">抱歉,此条评论已被作者删除</h6> <% else %> ... <div class="media-body"> <h6 class="media-heading"><%= link_to comment.name, user_path(User.find_by(user_name: comment.name)) %> / <%= "#{comment.floor}楼" %> <% if User.find_by(user_name: comment.name) == current_user %> <%= link_to '编辑', edit_article_comment_path(comment.article, comment) %> <%= link_to '删除', [comment.article, comment], method: :delete %> <% end %> </h6> <%= markdown(comment.content) %> </div> ...</div>
- ActiveRecord中实现软删除
- PHP中实现ActiveRecord模式的一些项目总结
- jdbc 实现ActiveRecord
- ActiveRecord
- ActiveRecord
- ActiveRecord
- activerecord中拼接SQL语句
- [ROR] rails migration 中继承 ActiveRecord::Migration[5.1] 带版本号实现原理
- ActiveRecord migration的Java实现 -- Timachine
- 在Castle ActiveRecord中使用NHibernate
- Castle ActiveRecord 中使用Access数据库
- ActiveRecord中实体类问题解决方法
- Castle ActiveRecord中CountQuery的使用
- Yii框架中ActiveRecord使用Relations
- rails 4 中 在 ActiveRecord 中指定表名
- ActiveRecord中Find与Where区别
- Rails中Array转为ActiveRecord::Relation
- rails 4 中 在 ActiveRecord 中指定表名
- POJ1759-Garland
- 认识CoreData—多线程
- Android之ActionBar(demo)
- Android MediaRecorder 后台视频录制
- HDU1711-KMP算法
- ActiveRecord中实现软删除
- pch文件配置
- Python 基础归纳整理
- python——函数
- Give the common ancestor of all the deepest nodes of a tree
- 最近公共祖先
- android开发 使用RecycleView加载数据
- 使用vlc实现视频TS流的推送
- Exception:Failed to start component [StandardEngine[Catalina... NoClassDefFoundError:org/apache/log4