Rails如何将ActionText字段复制到纯文本字段并批量更新历史数据
Rails ActionText历史数据同步纯文本字段迁移修正方案
原有代码问题
原有迁移代码不生效主要存在两个核心错误:
action_text_rich_texts.record_id[d]不符合ActiveRecord查询语法,无法正确获取关联的富文本记录- 你配置的
before_save回调是将纯文本内容存储到Doc模型的content_plain_text字段,但原有迁移代码在新建独立的Content模型记录,逻辑不匹配
最优解决方案
你的Doc模型已经通过has_rich_text :content关联了ActionText富文本字段,直接通过关联读取内容即可,不需要手动查询action_text_rich_texts表,修正后的迁移代码如下:
class CopyContentToContentPlainText < ActiveRecord::Migration[6.0] def up # 重置Doc模型列缓存,避免迁移运行时不识别新增的content_plain_text字段 Doc.reset_column_information Doc.find_each do |d| # 直接通过关联获取富文本的纯文本内容 plain_text = d.content.body.to_plain_text # 跳过验证和回调直接更新字段,提升批量处理效率 d.update_column(:content_plain_text, plain_text) end end def down # 回滚时清空字段值,可选 Doc.update_all(content_plain_text: nil) end end
特殊场景适配
场景1:纯文本字段存储在独立Content表
如果你确认content_plain_text是存储在独立的Content表中,可使用以下代码:
class CopyContentToContentPlainText < ActiveRecord::Migration[6.0] def up Doc.find_each do |d| plain_text = d.content.body.to_plain_text # 避免重复创建关联记录,已存在则更新,不存在则新建 Content.find_or_create_by(doc_id: d.id) do |content| content.content_plain_text = plain_text end end end end
场景2:无法通过模型关联读取富文本内容
如果因为特殊情况无法通过Doc模型关联读取富文本,可直接查询action_text_rich_texts表获取内容:
class CopyContentToContentPlainText < ActiveRecord::Migration[6.0] def up Doc.reset_column_information Doc.find_each do |d| # 手动匹配关联字段获取富文本记录,record_type需和Doc模型类名一致 rich_text = ActionText::RichText.find_by( record_type: 'Doc', record_id: d.id, name: 'content' ) next unless rich_text plain_text = rich_text.body.to_plain_text d.update_column(:content_plain_text, plain_text) end end end
注意事项
- 批量处理大量数据时,
find_each会默认分批加载1000条记录,避免内存溢出 - 使用
update_column跳过模型验证和回调,不会触发你已配置的before_save逻辑,避免重复执行
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

