Ruby on Rails 之 Action Text 富文本指南:Trix 编辑器、RichText 模型与 Active Storage 的完整实战解析 📅 发布时间:2026/9/8 22:17:15 👁 浏览次数: Ruby on Rails 之 Action Text 富文本指南Trix 编辑器、RichText 模型与 Active Storage 的完整实战解析【免费下载链接】railsRuby on Rails项目地址: https://gitcode.com/GitHub_Trending/rai/railsAction Text 是 Ruby on Rails 官方仓库中的富文本解决方案为 Rails 应用带来开箱即用的富文本内容编辑与渲染能力。本文以 actiontext/README.md 为核心骨架结合本仓库内 Action Text 的模型、引擎、辅助方法、生成器源码与视图实现讲解其端到端工作方式、核心 API、底层数据流与工程实践。读完本文你将掌握has_rich_text的完整用法、RichText 的存取与渲染链路、附件/加密等高级配置并能够在自己的 Rails 应用中正确安装与定制 Action Text。Action Text 是什么把富文本编辑变成 Rails 的一等公民README 的第一句话概括了它的定位Action Text 为 Rails 带来富文本内容与编辑能力。它把「富文本编辑器」和「服务端内容模型」打通形成一条完整的链路前端编辑内置 Trix 编辑器负责格式化、超链接、引用、列表、嵌入式图片与图片画廊等一切编辑交互后端存储Trix 产生的富文本内容被保存到独立的RichText模型中并与应用中任意已有的 Active Record 模型关联文件托管富文本中嵌入的图片及其他附件自动交由 Active Storage 存储并与上述RichText模型关联。也就是说你不需要自己维护编辑器集成、HTML 清洗、附件上传三套各自为政的方案。README 也提示官方还维护了一份更完整的 Action Text Overview 指南本仓库的对应文档源位于该路径可进一步深入。端到端架构从一次点击到一行 SQL 记录先看一张「内容从编辑器流到数据库」的链路图文本示意用户在 Trix 中编辑/拖入图片 │ ▼ Trix 输出含 action-text-attachment sgid... 的 HTML │ ▼ has_rich_text :content 写入 Message#content │ ▼ RichText 记录serialize :body → ActionText::Content保存 HTML │ before_validation 自动提取 sgid → has_many_attached :embeds ▼ 嵌入文件 → Active StorageBlob / Attachment 表前端Trix 编辑器生成的 HTML 形态编辑器输出不是普通文本而是一段可被 Action Text 理解、包含附件引用的 HTML。例如一条消息的 content 被存储为h1Funny Times!/h1 p看这张照片/p action-text-attachment sgidBAh7CEkiCG… caption一辆赛车/action-text-attachment其中action-text-attachment标签是服务端识别附件的统一约定sgidSigned Global ID指向某个可附着的对象通常是 Active Storage Blob。服务端has_rich_text建立关联要让某个 Active Record 模型拥有富文本字段只需一行声明。来自 attribute.rb 文档中的经典示例class Message ActiveRecord::Base has_rich_text :content end message Message.create!(content: h1Funny times!/h1) message.content? # true message.content # #ActionText::RichText ... message.content.to_s # h1Funny times!/h1 message.content.to_plain_text # Funny times!源码中has_rich_text通过class_eval为你生成两个实例方法content返回「懒加载的关联 RichText 记录必要时即时构建」content?判断是否存在对应记录底层再声明一个has_one :rich_text_content多态关联autosave: true、dependent: :destroy实现「改动后自动保存、父记录删除时级联清理」。has_rich_text支持的选项汇总自 attribute.rb选项默认值作用encryptedfalse为true时富文本字段使用非确定性加密存储底层换用ActionText::EncryptedRichTextstrict_loadingstrict_loading_by_default默认 false为true时对该关联强制 strict loadingstore_if_blanktrue为false时若赋空值则不创建空白的 RichText 记录而是标记销毁已有记录一个更完整的声明示例class Article ApplicationRecord has_rich_text :body, encrypted: true, strict_loading: true, store_if_blank: true end防 N1预加载作用域has_rich_text同时为每个字段生成两个预加载作用域另有一个全局作用域见 attribute.rbMessage.all.with_rich_text_content # 只预载 body Message.all.with_rich_text_content_and_embeds # 预载 body 嵌入附件 Message.all.with_all_rich_text # 预载该模型全部富文本字段其中with_rich_text_content实为includes(rich_text_content)_and_embeds版本进一步includes(rich_text_content: { embeds_attachments: :blob })能显著降低列表页的查询次数。RichText 记录body 的序列化、附件提取与纯文本/多格式输出ActionText::RichText是这套体系的数据核心位于 rich_text.rb继承自抽象基类 record.rbActionText::Record ActiveRecord::Base。它做了三件关键的事1. body 的序列化HTML 片段以ActionText::Content形式存库serialize :body, coder: ActionText::Content belongs_to :record, polymorphic: true, touch: truebody列在数据库中保存的是 Trix/编辑器产生的 HTML 字符串落库时经由ActionText::Content编解码。ActionText::Content见 content.rb本质上是对 HTML 片段的包装器负责规范化、解析、渲染与序列化。构造时它会做一次 canonicalization例如把编辑器形态的附件标签、附件画廊、Markdown 原始标签统一收敛为action-text-attachment的规范 HTML。2. 附件自动提取embeds与 Active Storage 对接has_many_attached :embeds before_validation do self.embeds body.attachables.grep(ActiveStorage::Blob).uniq if body.present? end在每次校验前RichText 都会扫描body中所有 attachable通过ActionText::Content#attachables解析 sgid 得到对象过滤出ActiveStorage::Blob去重后挂到embeds上。这正是 README 所述「嵌入图片等附件自动使用 Active Storage 存储并关联到 RichText 模型」的代码落点。3. 内容输出面向展示与消费的多种形态RichText 对body做了方法委托并内置三种输出方法作用示例to_s安全渲染为带布局的 HTML 字符串h1Funny times!/h1to_plain_text去掉标签、实体被转码为普通文本Funny times!to_markdown(attachment_links: false)转换为 Markdown附件默认输出转义方括号文本# Funny times!to_editor_html输出可在编辑器内继续编辑的 HTML含附件内联预览旧名to_trix_html已废弃见下文说明注意to_plain_text/to_markdown的返回结果不是 HTML-safe 的直接渲染到浏览器前需另行消毒。另外在to_markdown(attachment_links: true)时附件会被渲染成带 URL 的 Markdown 链接这会依赖渲染上下文Controller 或 Mailer 动作URL 生成失败时会抛出异常——设计上是为了避免在无法生成完整 URL 的场合如队列任务误用。to_editor_html内部经由RichText.editor.as_editable(canonical_fragment)把规范内容还原为可编辑形态当前默认编辑器为 Trix见下文引擎配置并将附件预览图渲染为可回显的img。干净安全的渲染是默认项to_s之所以安全是因为渲染路径经过了消毒。渲染辅助定义在 content_helper.rbmattr_accessor(:sanitizer, default: Rails::HTML4::Sanitizer.safe_list_sanitizer.new)render_action_text_content先渲染附件局部模板再对结果做安全列表消毒action-text-attachment、figure、figcaption标签及附件的属性集合会被加入白名单见sanitizer_allowed_tags与sanitizer_allowed_attributes。应用可通过ActionText::ContentHelper.allowed_tags、allowed_attributes、scrubber或引擎的config.action_text.sanitizer_vendor自定义策略。附件体系action-text-attachment与 attachable 契约附件标签与属性白名单附件在 HTML 中的落点是一个统一标签。默认标签名可在引擎中配置见下源码默认值在 attachment.rbmattr_accessor :tag_name, default: action-text-attachment ATTRIBUTES %w( sgid content-type url href filename filesize width height previewable presentation caption content ).freezeActionText::Attachment包装「一个标签节点 一个可附着对象」提供to_html、to_plain_text、to_markdown等方法。对象自身可通过实现attachable_plain_text_representation/attachable_markdown_representation方法自定义其在纯文本、Markdown 中的呈现class Person ApplicationRecord include ActionText::Attachable def attachable_plain_text_representation(caption) [#{name}] end end附件画廊Gallery同样是富文本中常见的能力ActionText::AttachmentGallery会把连排的action-text-attachment识别为画廊并按figure.gallery结构渲染。Active Storage Blob 的默认 attachable 行为引擎初始化器见 engine.rb在:active_storage_blob加载完成后include ActionText::Attachable因此所有 Blob 天然可嵌入富文本ActiveSupport.on_load(:active_storage_blob) do include ActionText::Attachable def previewable_attachable? representable? end def attachable_plain_text_representation(caption nil) [#{caption || filename}] end # ... endAttachable模块attachable.rb通常需要对象实现to_attachable_sgid/ 具备sgid能力服务端据此在解析 HTML 时把标签还原成真实对象缺失时降级为Attachables::MissingAttachable见 attachables 目录。这也是「富文本内容天然携带可解析的附件引用、而非死板的img src」的关键设计。附件的渲染局部模板附件在页面上的呈现通过局部模板完成仓库中内置以下视图安装时会被复制/引用到应用attachment_galleries/_attachment_gallery.html.erb画廊容器attachables/_content_attachment.html.erb、_remote_image.html.erb、_missing_attachable.html.erb不同类型的 attachablecontents/_content.html.erb 与对应的布局 partialto_s渲染时套用的默认布局active_storage/blobs/_blob.html.erbBlob 附件图片预览 / 文件下载的呈现模板安装生成器会把它复制进应用供覆盖定制。引擎接入方式Action Text 如何成为 Rails 的一部分ActionText::Engineengine.rb作为 Rails Engine 装配了所有能力依赖active_record、active_storage、action_controller等 railtie初始化器把ActionText::Attributeinclude 进 Active Record、把ActionText::Encryptionprepend 进去支持encrypted: true并为ActiveStorage::Blob、Controller/Mailer、System Test Case 注入对应能力通过isolate_namespace ActionText提供action_text命名空间。引擎配置项一览可在config/application.rb或环境配置中设置配置项默认值说明config.action_text.editor:trix当前生效的编辑器名从editors注册表中取出config.action_text.editors{ trix: {} }编辑器注册表继承式配置对应 editor/registry.rbconfig.action_text.attachment_tag_nameaction-text-attachment附件在 HTML 中的标签名会被写入ActionText::Attachment.tag_nameconfig.action_text.sanitizer_vendornil指定消毒器实现厂商klass.safe_list_sanitizer编辑器是可扩展的config.action_text.editor :trix默认指向 Trix引擎通过Editor::Registry在 RichText 加载时完成解析。渲染内容回编辑器时RichText.editor.as_editable(fragment)负责把存储态 HTML 转换成对应编辑器的可编辑格式Trix 编辑器逻辑见 trix_editor.rb 与 trix_conversion.rb。加密富文本EncryptedRichText只要has_rich_text传encrypted: true关联就会指向ActionText::EncryptedRichTextclass EncryptedRichText RichText encrypts :body end见 encrypted_rich_text.rb。它通过ActiveRecord::Encryption的非确定性加密对body列整体加密其余渲染/附件能力与普通 RichText 完全一致——适合正文需要静态加密的业务如草稿、隐私内容。安装与实践从零接入一个 Rails 应用仓库的安装生成器位于 install_generator.rb并暴露为action_text:install任务任务定义见 tasks/actiontext.rake。典型执行方式bin/rails action_text:install生成器实际完成的步骤安装 JS 依赖通过当前 JS 包管理器安装rails/actiontext以及编辑器依赖默认 Trix并把import rails/actiontext、import trix追加到app/javascript/application.js若应用使用 importmap则向config/importmap.rb追加pin rails/actiontext, to: actiontext.esm.js等条目。复制样式与视图生成app/assets/stylesheets/actiontext.css内含.trix-content等排版/画廊样式并把 active_storage/blobs/_blob.html.erb 与 contents/_content.html.erb 布局 复制到应用内便于按项目定制附件呈现。复制迁移执行rails_command railties:install:migrations FROMactive_storage,action_text把 Active Storage 与 Action Text 的迁移源位于 actiontext/db/migrate灌入应用后运行bin/rails db:migrate建表。可选测试夹具模板若启用了 TestUnit还会为富文本字段生成fixtures.yml生成器见 test_unit 安装生成器。如需更换编辑器安装时指定bin/rails action_text:install --editortrix注意多态关联会把类名存入数据库即action_text_rich_texts.record_type列。若日后重命名使用了has_rich_text的模型类必须同步更新该列中的类名源码注释在 attribute.rb 中有明确提醒。接入后典型的完整用法是模型has_rich_text 表单提供富文本输入 视图展示富文本字段。例如控制器把参数直接写入关联# app/controllers/messages_controller.rb def create message Message.create!(message_params) end private def message_params params.require(:message).permit(:content) # content 即富文本 HTML含附件标签 end展示时message.content已能安全输出渲染好的 HTML经 sanitizer 附件 partial直接作为视图内容使用即可。前端资源与开发工作流npm、资源管线与构建同步README 的 Development 一节交代了 Action Text 前端资源的发布策略这部分对贡献者尤其重要Action Text 的 JavaScript同时以两种形态分发作为 npm 模块rails/actiontext配置见 package.json打包脚本由 rollup.config.js 定义以及通过资产管线作为actiontext.js提供Trix 也被镜像为trix.js。为保证两者始终一致每次改动 JavaScript 源码或升级 Trix 依赖后都必须运行yarn build并提交构建产物即app/assets/javascripts/下的actiontext.js、actiontext.esm.js等。引擎初始化器也会把这些文件加入assets.precompile列表见 engine.rb。CSS 改动必须人工同步到app/assets/stylesheets/trix.cssREADME 明确指出不会自动生成。如果你只是使用 Action Text正常依赖 npm 版rails/actiontext 应用构建流程即可只有当你修改 Action Text 的 JS 源码或升级 Trix时才需要关心yarn build与提交产物的约定。系统测试与测试数据Action Text 为 Rails 系统测试提供了一个辅助模块 system_test_helper.rb引擎初始化器会自动把它 include 进ActionDispatch::SystemTestCase方便在端到端测试中驱动 Trix 编辑器交互。本仓库 actiontext/test 下的集成/系统测试如 integration是理解真实用法的活文档。小结Action Text 的设计要点回顾围绕 actiontext/README.md 的核心承诺结合本仓库源码可归纳出四条要点编辑端到存储端的整链闭环Trix 编辑 → HTML 含action-text-attachment(sgid)→ 任意 Active Record 模型的has_rich_text字段 →RichText的body序列化为ActionText::Content。附件统一走 Active Storagebefore_validation自动把 body 中的 Blob 提取到has_many_attached :embeds存储、预览、下载都由 Active Storage 及其 Blob 局部模板负责。渲染安全是内建默认输出路径统一经 safe-list sanitizer 消毒figure/figcaption/附件标签及白名单属性被显式放行。可配置与可扩展编辑器注册表、附件标签名、消毒器厂商、加密存储等均有明确的引擎配置项与源码落点。对于需要在 Rails 应用中交付「所见即所得正文 图片/文件嵌入」场景的开发者Action Text 是一条覆盖模型层、视图层与资产层的完整官方路径。更多进阶内容可继续阅读仓库内的 Action Text Overview 指南以及 actiontext 测试目录 中的用例。【免费下载链接】railsRuby on Rails项目地址: https://gitcode.com/GitHub_Trending/rai/rails创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考