Rails 在 has_many 后是否要有 dependent?

sec · 2017年02月07日 · 最后由 sec 回复于 2017年02月10日 · 1814 次阅读

RailsGuide 中提到: 在关联中设置 :dependent 选项,可以保证父对象删除后,子对象也会被删除。

疑问: 如果 has_many 后不使用 dependent, 删除 Ao 中数据,将导致 Bo 没有关联的父对象 Id,这样不就导致数据关联查询出现问题?是否将所有 has_many 后都添加 dependent

class Ao < ApplicationRecord
   has_many :bos, :dependent => :destroy 
end

class Bo < ApplicationRecord
   belongs_to :ao
end

看情况,有时候不要关联删除比较好

根据情况 设定 dependent 吧

dependent: :nullify causes the foreign keys to be set to NULL. Callbacks are not executed

这个没有死标准,看关联的数据后续还有没有保留的必要,如果没有,就可以直接 dependent: :destroy;如果有,看要不要保留数据里的外键(比如可能用于后续的数据统计分析需要),如果有,就连 :dependent 都不用声明了,所关联数据就不会动了,如果没有,可以声明 dependent: :nullify 将外键置空。

举个例子吧,比如我有一个 CMS 系统,实体有 Page(网页)、Picture(网页上的照片)以及 Visit(网页访问,记录来访用户信息以及受访网页)。一个网页上会有多个照片,同时也会有多个访问记录。一般来说,如果我删除了网页,那么原来网页上的照片也没有留着的意义了,所以我们期待一旦删了网页,也要清除网页上的照片。另一方面,尽管我删除了网页,但是我仍然想要知道整个站点历史访问量情况,包括 PV(要记得访问的是哪个 page,也就是 page_id 外键有必要保留,不能被置空)、UV 等,那么访问记录的数据我是不想随着网页被删而同时被清除的,那么这个业务的代码就是:

class Page < ActiveRecord::Base
  has_many :pictures, dependent: :destroy
  has_many :visits        # 关联数据不声明 dependent,将不会被自动删除
end

事实上,我能想到的关联数据不清除的场景,基本也都是一些有审计用途的数据了。

一种组合关系而已,有级联删除的需求就加上,没有这种需求就别加
举个🌰:管理员要删除一个角色,就要删除这个角色所拥有的所有权限

###dependent 的选项分为 destroy, delete,nullify

destroy: 表示会同时删除它拥有的级联关系 (包括内存对象和数据库记录)
delete : 表示会删除数据库记录但不调用对象的 destroy 方法去销毁内存对象
nullify : 表示会用来将关联对象的外键设置为 null

sec 关闭了讨论 02月10日 16:23
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册