如何检测ActionText富文本内容是否发生变更?
Rails Action Text 富文本内容变更检测方案
因为has_rich_text是将富文本内容存储在关联的ActionText::RichText模型中,而非Article自身的数据库字段,所以常规的previous_changes、*_previously_changed?等方法无法直接检测到content的变更。以下是几种可行的解决方式:
1. 直接检测关联模型的变更
由于content是ActionText::RichText类型的关联对象,可直接调用该对象的变更追踪方法:
article.update(name: 'test', content: 'test content changed') # 检查content的body是否发生变更 article.content&.body_previously_changed? # 返回 true/false # 查看content的具体变更记录 article.content&.previous_changes # 包含body字段的变更信息
2. 在模型中封装自定义方法
为了和常规字段的检测方式保持一致,可以在Article模型中封装自定义方法:
# app/models/article.rb class Article < ApplicationRecord has_rich_text :content # 模拟常规字段的_previously_changed?方法 def content_previously_changed? content&.body_previously_changed? || (content.present? && content.previously_changed?) end # 获取content的变更记录 def content_previous_changes content&.previous_changes || {} end end
之后就可以像使用常规字段方法一样调用:
article.update(name: 'test', content: 'test content changed') article.content_previously_changed? # 返回 true article.content_previous_changes # 返回body的变更详情
3. 在回调中对比内容变更
如果需要在保存前后处理变更逻辑,可以在回调中直接对比内容的新旧值:
# app/models/article.rb class Article < ApplicationRecord has_rich_text :content before_save :handle_content_change private def handle_content_change # 获取保存前的内容(若之前无内容则为空字符串) original_body = content_was&.body || "" # 获取即将保存的新内容 new_body = content.body || "" if original_body != new_body # 这里编写内容变更后的业务逻辑 puts "富文本内容已修改" end end end
核心原因说明
Action Text的has_rich_text本质是为模型创建了一个一对一的ActionText::RichText关联,所有富文本内容实际存储在该关联模型的body字段中。Active Record的默认变更追踪仅针对模型自身的数据库字段,不会自动追踪关联模型的字段变更,因此需要通过关联对象来检测富文本内容的变化。
内容的提问来源于stack exchange,提问作者Lam Phan
相关产品推荐
相关产品推荐

