By Ronak Gothi
Action Text is a very powerful rails feature which uses Trix editor from basecamp under the hood, In this article we will understand how to use ActionText to work with different media format.
Let's create a new Blog Application for this demo.
1
2
rails new action-text-demo -d postgresql
rails g scaffold Blog
Install action text into your app
1
2
bin/rails action_text:install
bin/rails db:create db:migrate RAILS_ENV=development
In the blog model add a field content which is a rich_text
1
2
3
class Blog < ApplicationRecord
has_rich_text :content
end
Note: the content field is managed by the table active_storage_attachments, hence blog table do not have to
create the field content seperately.
In the views add the form field
1
2
3
4
5
6
<%# app/views/messages/_form.html.erb %>
<div class="field">
<%= form.label :content %>
<%= form.rich_text_area :content %>
</div>
Display the rich_text content in /blog/show
1
2
<%# app/views/blogs/show.html.erb %>
<%= @blog.content %>
Permit the content attribute in the controller
1
2
3
4
#app/controllers/blogs_controller.rb
def blog_params
params.require(:blog).permit(:content)
end
Visit http://localhost:3000/blogs/new We would see the following screen

Now let's try uploading

You'll notice the following error because, ActiveText needs image_processing gem to generate preview image of
the uploaded images.
1
LoadError (Generating image variants require the image_processing gem. Please add `gem 'image_processing', '~> 1.2'` to your Gemfile.):
Let's install the gem and try again, and it works.

However, we have the following issue
Let's edit the active_storage blob file to generate content as per the file uploaded instead of using the default image tags.
<video> tag if the blob is of type Video audio tag if the blob is of type Audio.embed tag if the blob is of type PDF.iFrame for docx upload.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<%# www/app/views/active_storage/blobs/_blob.html.erb %>
<figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
<% if blob.video? %>
<video
controls="false"
width="100%"
poster=<%= polymorphic_url(blob.representation(resize_to_limit: [ 1024, 768 ])) %>
>
<source src= <%= rails_blob_url(blob) %>, type=<%= blob.content_type %> >
</video>
<% elsif blob.audio? %>
<audio controls="true" width="100%" preload="metadata">
<source src= <%= rails_blob_url(blob) %>, type=<%= blob.content_type %> >
</audio>
<% elsif blob.content_type == 'application/pdf' %>
<embed src=<%= rails_blob_url(blob) %> width="800" height="500"
type="application/pdf">
<% elsif blob.content_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' %>
<iframe src='https://view.officeapps.live.com/op/embed.aspx?src=<%= rails_blob_url(blob) %>' width='100%' height='500px' frameborder='0'>
</iframe>
<% elsif blob.representable? %>
<%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
<% end %>
<figcaption class="attachment__caption">
<% if caption = blob.try(:caption) %>
<%= caption %>
<% else %>
<span class="attachment__name"><%= blob.filename %></span>
<span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
<% end %>
<span> ยท </span>
<%= link_to "Download", rails_blob_path(blob, disposition: "attachment") %>
</figcaption>
</figure>
Add the above tags to ActionText::ContentHelper.allowed_tags list
1
2
3
4
5
6
7
8
9
10
11
12
#config/application.rb
config.after_initialize do
ActionText::ContentHelper.allowed_attributes.add 'style'
ActionText::ContentHelper.allowed_attributes.add 'controls'
ActionText::ContentHelper.allowed_attributes.add 'poster'
ActionText::ContentHelper.allowed_tags.add 'video'
ActionText::ContentHelper.allowed_tags.add 'audio'
ActionText::ContentHelper.allowed_tags.add 'source'
ActionText::ContentHelper.allowed_tags.add 'embed'
ActionText::ContentHelper.allowed_tags.add 'iframe'
end
And the uploaded media uploaded via Rails ActionText content is now viewable as embedded content.

embed tag