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