如何获取模型保存前版本?判断ActiveRecord新旧模型生成的External模型差异
解决方案:判断ActiveRecord新旧版本生成的External模型差异
以下是几个可靠的实现思路,无需将External模型存入数据库:
1. 利用before_save缓存旧版本External模型
在模型保存前,提前将未修改的AR实例转换为External模型并缓存,保存后直接对比新旧External实例:
class YourModel < ActiveRecord::Base before_save :cache_old_external_state after_save :trigger_sync_if_needed private def cache_old_external_state # 用当前未修改的AR实例生成旧External模型 @old_external = to_external_model end def trigger_sync_if_needed new_external = to_external_model # 对比新旧External模型,有差异则触发同步 SyncExternalJob.perform_async(id) if @old_external != new_external end end
关键前提:你的External模型(或转换后的Hash/结构体)必须正确实现==方法,确保能递归对比所有嵌套字段、关联转换后的内容。
2. 结合previous_changes针对性对比
通过saved_changes/previous_changes拿到变更属性,先判断这些属性是否会影响External模型输出,再按需对比:
class YourModel < ActiveRecord::Base # 定义所有会影响External模型的AR属性(含关联相关字段) EXTERNAL_RELEVANT_ATTRS = [:name, :email, :address, :order_ids] after_save :trigger_sync_if_needed private def trigger_sync_if_needed # 检查是否有影响External模型的属性变更 changed_relevant_attrs = saved_changes.keys & EXTERNAL_RELEVANT_ATTRS return if changed_relevant_attrs.empty? # 用变更前的属性重建旧AR实例 old_ar = self.dup previous_changes.each do |attr, (old_val, _)| old_ar.send("#{attr}=", old_val) end # 对比新旧External模型 old_external = old_ar.to_external_model new_external = to_external_model SyncExternalJob.perform_async(id) if old_external != new_external end end
关联变更处理:如果关联模型的变更会影响主模型的External输出,可在关联模型的回调中标记主模型需要同步(比如给主模型加needs_sync字段,关联模型变更时设为true)。
3. 用版本化插件获取旧AR实例
借助paper_trail这类版本化插件,直接获取保存前的AR版本实例,再转换为External模型对比:
# 先安装并启用paper_trail class YourModel < ActiveRecord::Base has_paper_trail after_save :trigger_sync_if_needed private def trigger_sync_if_needed # 获取上一个版本的AR实例 previous_version = versions.last&.reify return unless previous_version old_external = previous_version.to_external_model new_external = to_external_model SyncExternalJob.perform_async(id) if old_external != new_external end end
注意:paper_trail会在数据库中存储AR模型的版本记录,但仅存属性变更,比存储完整External模型轻量;若不需要长期保留版本,可在对比后清理旧版本记录。
内容的提问来源于stack exchange,提问作者Ákos Vandra-Meyer
相关产品推荐
相关产品推荐

