Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
More atrubyonrails.org:

Action Text Overview

This guide provides you with all you need to get started in handling rich textcontent.

After reading this guide, you will know:

  • What Action Text is, and how to install and configure it.
  • How to create, render, style, and customize rich text content.
  • How to handle attachments.

1. What is Action Text?

Action Text facilitates the handling and display of rich text content. Rich textcontent is text that includes formatting elements such as bold, italics, colors,and hyperlinks, providing a visually enhanced and structured presentation beyondplain text. It allows us to create rich text content, store it in a table, thenattach it to any of our models.

Action Text includes aWYSIWYG editorcalled Trix, which is used in web applications to provide users with auser-friendly interface for creating and editing rich text content. It handleseverything from providing enriching capabilities like the formatting of text,adding links or quotes, embedding images, and much much more. Seethe Trixeditor website for examples.

The rich text content generated by the Trix editor is saved in its own RichTextmodel that can be associated with any existing Active Record model in theapplication. In addition, any embedded images (or other attachments) can beautomatically stored using Active Storage (which is added as a dependency) andassociated with that RichText model. When it's time to render content, ActionText processes the content by sanitizing it first so that it's safe to embeddirectly into the page's HTML.

Most WYSIWYG editors are wrappers around HTML’scontenteditable andexecCommand APIs. These APIs were designed by Microsoft to support liveediting of web pages in Internet Explorer 5.5. They were eventuallyreverse-engineered and copied by other browsers. Consequently, these APIs werenever fully specified or documented, and because WYSIWYG HTML editors areenormous in scope, each browser's implementation has its own set of bugs andquirks. Hence, JavaScript developers are often left to resolve theinconsistencies.

Trix sidesteps these inconsistencies by treatingcontenteditable as an I/O device: when input makes its way to the editor, Trixconverts that input into an editing operation on its internal document model,then re-renders that document back into the editor. This gives Trix completecontrol over what happens after every keystroke and avoids the need to useexecCommand and the inconsistencies that come along with it.

2. Installation

To install Action Text and start working with rich text content, run:

$bin/railsaction_text:install

It will do the following:

  • Installs the JavaScript packages fortrix and@rails/actiontext and addsthem to theapplication.js.
  • Adds theimage_processing gem for analysis and transformations of theembedded images and other attachments with Active Storage. Please refer to theActive Storage Overview guide for moreinformation about it.
  • Adds migrations to create the following tables that store rich text contentand attachments:action_text_rich_texts,active_storage_blobs,active_storage_attachments,active_storage_variant_records.
  • Createsactiontext.css which includes all Trix styles and overrides.
  • Adds the default view partials_content.html and_blob.html to renderAction Text content and Active Storage attachment (aka blob) respectively.

Thereafter, executing the migrations will add the newaction_text_* andactive_storage_* tables to your app:

$bin/railsdb:migrate

When the Action Text installation creates theaction_text_rich_texts table, ituses a polymorphic relationship so that multiple models can add rich textattributes. This is done through therecord_type andrecord_id columns,which store the ClassName of the model, and ID of the record, respectively.

With polymorphic associations, a model can belong to more than one othermodel, on a single association. Read more about it in theActive RecordAssociationsguide.

Hence, if your models containing Action Text content use UUID values asidentifiers, then all models that use Action Text attributes will need to useUUID values for their unique identifiers. The generated migration for ActionText will also need to be updated to specifytype: :uuid for the recordreferences line.

t.references:record,null:false,polymorphic:true,index:false,type: :uuid

3. Creating Rich Text Content

This section explores some of the configurations you'll need to follow to createrich text.

The RichText record holds the content produced by the Trix editor in aserializedbody attribute. It also holds all the references to the embeddedfiles, which are stored using Active Storage. This record is then associatedwith the Active Record model which desires to have rich text content. Theassociation is made by placing thehas_rich_text class method in the modelthat you’d like to add rich text to.

# app/models/article.rbclassArticle<ApplicationRecordhas_rich_text:contentend

There's no need to add thecontent column to your Article table.has_rich_text associates the content with theaction_text_rich_texts tablethat has been created, and links it back to your model. You also may choose toname the attribute to be something different fromcontent.

Once you have added thehas_rich_text class method to the model, you can thenupdate your views to make use of the rich text editor (Trix) for that field. Todo so, use arich_textareafor the form field.

<%# app/views/articles/_form.html.erb %><%=form_withmodel:articledo|form|%><divclass="field"><%=form.label:content%><%=form.rich_textarea:content%></div><%end%>

This will display a Trix editor that provides the functionality to create andupdate your rich text accordingly. Later we'll go into details abouthow toupdate the styles for theeditor.

Finally, to ensure that you can accept updates from the editor, you will need topermit the referenced attribute as a parameter in the relevant controller:

classArticlesController<ApplicationControllerdefcreatearticle=Article.create!params.expect(article:[:title,:content])redirect_toarticleendend

If the need arises to rename classes that utilizehas_rich_text, you will alsoneed to update the polymorphic type columnrecord_type in theaction_text_rich_texts table for the respective rows.

Since Action Text depends on polymorphic associations, which, in turn, involvestoring class names in the database, it's crucial to keep the data in sync withthe class names used in your Ruby code. This synchronization is essential tomaintain consistency between the stored data and the class references in yourcodebase.

4. Rendering Rich Text Content

Instances ofActionText::RichText can be directly embedded into a page becausethey have already sanitized their content for a safe render. You can display thecontent as follows:

<%=@article.content%>

ActionText::RichText#to_s safely transforms RichText into an HTML String. Onthe other handActionText::RichText#to_plain_text returns a string that is notHTML safe and should not be rendered in browsers without additional sanitization.You can learn more about Action Text's sanitization process in theActionText::RichTextdocumentation.

If there's an attached resource withincontent field, it might not showproperly unless you have the necessarydependencies for ActiveStorage installed.

5. Customizing the Rich Text Content Editor (Trix)

There may be times when you want to update the presentation of the editor tomeet your stylistic requirements, this section guides on how to do that.

5.1. Removing or Adding Trix Styles

By default, Action Text will render rich text content inside an element with the.trix-content class. This is set inapp/views/layouts/action_text/contents/_content.html.erb. Elements with thisclass are then styled by the trix stylesheet.

If you’d like to update any of the trix styles, you can add your custom stylesinapp/assets/stylesheets/actiontext.css, which includes both the full set ofstyles for Trix and the overrides needed for Action Text.

5.2. Customizing the Editor Container

To customize the HTML container element that's rendered around rich textcontent, edit theapp/views/layouts/action_text/contents/_content.html.erblayout file created by the installer:

<%# app/views/layouts/action_text/contents/_content.html.erb %><divclass="trix-content"><%=yield%></div>

5.3. Customizing HTML for Embedded Images and Attachments

To customize the HTML rendered for embedded images and other attachments (knownas blobs), edit theapp/views/active_storage/blobs/_blob.html.erb templatecreated by the installer:

<%# app/views/active_storage/blobs/_blob.html.erb %><figureclass="attachment attachment--<%=blob.representable??"preview":"file"%> attachment--<%=blob.filename.extension%>"><%ifblob.representable?%><%=image_tagblob.representation(resize_to_limit:local_assigns[:in_gallery]?[800,600]:[1024,768])%><%end%><figcaptionclass="attachment__caption"><%ifcaption=blob.try(:caption)%><%=caption%><%else%><spanclass="attachment__name"><%=blob.filename%></span><spanclass="attachment__size"><%=number_to_human_sizeblob.byte_size%></span><%end%></figcaption></figure>

6. Attachments

Currently, Action Text supports attachments that are uploaded through ActiveStorage as well as attachments that are linked to a Signed GlobalID.

6.1. Active Storage

When uploading an image within your rich text editor, it uses Action Text whichin turn uses Active Storage. However,Active Storage has somedependencies which are not providedby Rails. To use the built-in previewers, you must install these libraries.

Some, but not all of these libraries are required and they are dependent on thekind of uploads you are expecting within the editor. A common error that usersencounter when working with Action Text and Active Storage is that images do notrender correctly in the editor. This is usually due to thelibvips dependencynot being installed.

6.1.1. Attachment Direct Upload JavaScript Events

Action Text dispatchesActive Storage Direct UploadEvents during theFile attachment lifecycle.

In addition to the typicalevent.detail properties, Action Text alsodispatches events with anevent.detail.attachmentproperty.

Event nameEvent targetEvent data (event.detail)Description
direct-upload:start<input>{id, file}A direct upload is starting.
direct-upload:progress<input>{id, file, progress}As requests to store files progress.
direct-upload:error<input>{id, file, error}An error occurred. Analert will display unless this event is canceled.
direct-upload:end<input>{id, file}A direct upload has ended.

It is possible for files uploaded by Action Text throughActive StorageDirect Uploads to never beembedded within rich text content. Considerpurging unattacheduploads regularly.

6.2. Signed GlobalID

In addition to attachments uploaded through Active Storage, Action Text can alsoembed anything that can be resolved by aSignedGlobalID.

A Global ID is an app-wide URI that uniquely identifies a model instance:gid://YourApp/Some::Model/id. This is helpful when you need a singleidentifier to reference different classes of objects.

When using this method, Action Text requires attachments to have a signed globalID (sgid). By default, all Active Record models in a Rails app mix in theGlobalID::Identification concern, so they can be resolved by a signed globalID and are thereforeActionText::Attachable compatible.

Action Text references the HTML you insert on save so that it can re-render withup-to-date content later on. This makes it so that you can reference models andalways display the current content when those records change.

Action Text will load up the model from the global ID and then render it withthe default partial path when you render the content.

An Action Text Attachment can look like this:

<action-text-attachmentsgid="BAh7CEkiCG…"></action-text-attachment>

Action Text renders embedded<action-text-attachment> elements by resolvingtheir sgid attribute of the element into an instance. Once resolved, thatinstance is passed along to a render helper. As a result, the HTML is embeddedas a descendant of the<action-text-attachment> element.

To be rendered within Action Text<action-text-attachment> element as anattachment, we must include theActionText::Attachable module, whichimplements#to_sgid(**options) (made available through theGlobalID::Identification concern).

You can also optionally declare#to_attachable_partial_path to render a custompartial path and#to_missing_attachable_partial_path for handling missingrecords.

An example can be found here:

classPerson<ApplicationRecordincludeActionText::Attachableendperson=Person.create!name:"Javan"html=%Q(<action-text-attachment sgid="#{person.attachable_sgid}"></action-text-attachment>)content=ActionText::Content.new(html)content.attachables# => [person]

6.3. Rendering an Action Text Attachment

The default way that an<action-text-attachment> is rendered is through thedefault path partial.

To illustrate this further, let’s consider a User model:

# app/models/user.rbclassUser<ApplicationRecordhas_one_attached:avatarenduser=User.find(1)user.to_global_id.to_s#=> gid://MyRailsApp/User/1user.to_signed_global_id.to_s#=> BAh7CEkiCG…

We can mixGlobalID::Identification into any model with a.find(id)class method. Support is automatically included in Active Record.

The above code will return our identifier to uniquely identify a model instance.

Next, consider some rich text content that embeds an<action-text-attachment>element that references the User instance's signed GlobalID:

<p>Hello,<action-text-attachmentsgid="BAh7CEkiCG…"></action-text-attachment>.</p>

Action Text uses the "BAh7CEkiCG…" String to resolve the User instance. It thenrenders it with the default partial path when you render the content.

In this case, the default partial path is theusers/user partial:

<%# app/views/users/_user.html.erb %><span><%=image_taguser.avatar%><%=user.name%></span>

Hence, the resulting HTML rendered by Action Text would look something like:

<p>Hello,<action-text-attachmentsgid="BAh7CEkiCG…"><span><imgsrc="..."> Jane Doe</span></action-text-attachment>.</p>

6.4. Rendering a Different Partial for the action-text-attachment

To render a different partial for the attachable, defineUser#to_attachable_partial_path:

classUser<ApplicationRecorddefto_attachable_partial_path"users/attachable"endend

Then declare that partial. The User instance will be available as the userpartial-local variable:

<%# app/views/users/_attachable.html.erb %><span><%=image_taguser.avatar%><%=user.name%></span>

6.5. Rendering a Partial for an Unresolved Instance or Missing action-text-attachment

If Action Text is unable to resolve the User instance (for example, if therecord has been deleted), then a default fallback partial will be rendered.

To render a different missing attachment partial, define a class-levelto_missing_attachable_partial_path method:

classUser<ApplicationRecorddefself.to_missing_attachable_partial_path"users/missing_attachable"endend

Then declare that partial.

<%# app/views/users/missing_attachable.html.erb %><span>Deleted user</span>

6.6. Attachable via API

If your architecture does not follow the traditional Rails server-side renderedpattern, then you may perhaps find yourself with a backend API (for example,using JSON) that will need a separate endpoint for uploading files. The endpointwill be required to create anActiveStorage::Blob and return itsattachable_sgid:

{"attachable_sgid":"BAh7CEkiCG…"}

Thereafter, you can take theattachable_sgid and insert it in rich textcontent within your frontend code using the<action-text-attachment> tag:

<action-text-attachmentsgid="BAh7CEkiCG…"></action-text-attachment>

7. Miscellaneous

7.1. Avoiding N+1 Queries

If you wish to preload the dependentActionText::RichText model, assuming yourrich text field is namedcontent, you can use the named scope:

Article.all.with_rich_text_content# Preload the body without attachments.Article.all.with_rich_text_content_and_embeds# Preload both body and attachments.


Back to top
[8]ページ先頭

©2009-2025 Movatter.jp