如何在PaperTrail保存前覆盖object_changes,存入用户名替代用户ID
解决PaperTrail在TeamMember创建时存储用户名到object_changes的方案
要实现创建TeamMember时将用户名存入object_changes,而非仅存储用户ID,可以通过拦截PaperTrail的版本生成流程,手动修改变更记录内容。以下是两种实用方案:
方案一:替换user_id的变更值为用户名
在TeamMember模型中添加PaperTrail版本创建前的回调,直接把user_id的变更值替换为用户名:
class TeamMember < ApplicationRecord belongs_to :user has_paper_trail # 拦截版本创建流程,修改object_changes内容 before_create_version :replace_user_id_with_name private def replace_user_id_with_name(version) # 仅处理create事件的版本记录 return unless version.event == 'create' user_id_change = version.object_changes['user_id'] return unless user_id_change.present? && user.present? # 将user_id的变更值从ID替换为用户名 version.object_changes['user_id'] = [nil, user.name] end end
方案二:保留user_id,新增user_name变更字段
如果需要同时保留用户ID和用户名的变更记录,可以在object_changes中新增user_name字段:
class TeamMember < ApplicationRecord belongs_to :user has_paper_trail before_create_version :add_user_name_to_changes private def add_user_name_to_changes(version) return unless version.event == 'create' && user.present? # 在object_changes中新增user_name的变更记录 version.object_changes['user_name'] = [nil, user.name] end end
关键说明
- 代码依赖
TeamMember与User的belongs_to关联,创建时user必然存在(默认belongs_to为必填关联),因此可以安全获取user.name。 - 针对create事件无法使用
reify的问题,直接从version.object_changes中读取用户名即可,无需关联查询User,避免了用户删除后查询失败的问题。 - 回调中操作的
version.object_changes是未序列化的Ruby哈希,修改后会自动被PaperTrail序列化为JSON存入数据库。
内容的提问来源于stack exchange,提问作者john bowlee
相关产品推荐
相关产品推荐

