Skip to main content

Using the Trix Editor plus File Upload Attachments Discussion

General • Asked by Chris Oliver

Great vid, can this be done with the carrierwave gem?

Yep, just swap out the Shrine code on the Photos model and you're set.

how about ActiveStorage?

Should work for that too, since the JS is agnostic to any backend storage you might want to use. Direct uploads to S3 etc will work as well.

Hi Chris, I am trying to get the Direct uploads to S3 to work with trix. Can you offer some pointers/resources that may help me?


How hard is it to add trix to a selected input-field in administrate. What should be the best approach?

Really really easy. You need to add the JS and CSS to administrate's versions. Then you can create a custom field. I made one called FormattedText and just added the editor to the form.html.erb view for the field.

<div class="field-unitlabel">
<%= f.label field.attribute %>
<div class="field-unit
<%= f.hidden_field field.attribute, id: field.attribute %>
<trix-editor input="&lt;%= field.attribute %&gt;"></trix-editor>

wow that easy! Great. Thanks!

Great. Got it working after understanding that i had to add the js and scss to the actual gem. I have a hard time understanding javascript and the pipeline so I do have a question:

1) Why cant I add the code somewhere in the normal asset pipeline

2) How do I add the files in a production environment. Do I have to ssh into production to add the requires in both .js and sccs files inside the gem?

1. The admin compiles separate css and JS files. Your regular users will never have access to the admin, so it doesn't make sense to give them all your admin css and js.

2. They will be compiled automatically. Administrate already configures your app to have separate admin js and css files that are compiled via the normal asset pipeline. The asset pipeline can compile more than one file as output, but we don't generally do that so the user only has to download a minimal set of files. We only do here because sending those regular users the admin style and functionality doesn't make sense.

my local install of the administrate gem (/var/lib/gems/2.3.0/gems/administrate-0.8.1/lib/) will not move to production, and that is were I added the requires for trix.js and trix.scss. Wasn't this the right place to edit the files?

Yeah you should never edit a gem's source code. Install the administrate assets into your app using the generator and edit those to include trix.

Thanks a lot Chris!

learned something new today.

My last question:)
Should I create a new folder 'assets/javascript/admin' (because this is the route to the dashboard) and place/edit the administrate asset files there?

I don't think so, just use the administrate generator to create the administrate files. You don't need to create any folders yourself.

From what I've read trix doesn't allow any html tags in input. This is good for security but we use some custom css classes. How hard is it to add these to trix locally?

Hey Chris! That was a great episode. Special thanks for the part where you explain the details about image uploading. I've been implementing images processing for few Rails apps, nevertheless some aspects in this area felt like a black magic to me. For example, progress tracking for XHR requests was new.

Also now I know that axios has onUploadProgress callback. Neat. When you know what features to expect, it is much easier to find them.

How add post_id with Photo ?

did you find any solution?

How add association has_many :photos with post.rb after save ?

Hi! How to use jquery_ujs instead of rails-ujs to use trix gem?

xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken()); Rails. not work

You use


Hmm. So in this example the Post object has no association with Photo. Since Trix isn't handling any sort of deletion, we only add photos and never remove them. We also can't remove a Photo (or the attached image) when a Post is deleted since there's no relationship between them. And because Trix is handling the HTML for the image, I don't have an opportunity to add markup to the image to use, say, Imgix.js to handle responsive adaptations.

If I add a post-processor on the HTML (e.g., parse w/ Nokogiri and manipulate the images as needed), Trix is going to be disagreeable on edit. I could handle that on show and use fragment caching, I suppose. If I use JS to modify what I'm handing Trix, my final output is tied to the JS on a totally different view in an unrelated area of my website, and it's difficult to update down the road. Neither of these options fixes the lack of relationships, either, unfortunately.

How are others handling this in, say, a CMS for a media organization?

How did you end up handling it @coreyward:disqus ? I used a form of post-processing in the past with Refile, curious to know if you came up with a better solution?

I went for a half-baked solution. Photos belong_to Post, and I pass along the post ID when uploading to make that work. When a post is removed, so are the photos. For new posts, there’s no ID. I didn’t have time to store these separately or add a unique pre-persisting token to Post, but the logic there should work. For now a Post adopts all orphan images on save. This is fine since this isn’t end-User facing, so volume is low.

Removing photos without removing a post is more work. You need to handle the JS event Trix triggers when the photo is removed, but just mark it for removal on save instead of actually deleting it. Otherwise someone can cancel and the photo will break.

As for manipulations/transformations, I’m using Imgix to handle that. I built a the particular params I’m using into the controller that returns the image url for Trix. I’d rather that happen on render, but I didn’t have time/budget. If I need to change them in the future they’re easy enough to grep for, and if I want to be more dynamic I’ll use nokigiri to parse and render a srcset (and probably fragment cache for performance).

Images man…too much work.

Chris! Next video: Trix + ActiveStorage. :)

Stephane Le Boisselier


Thanks for this great job, i decide to replace Refile with Shrine, but got a problem. In my js xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken()); generate an error in JS Console, Rails is not define. I tried to update my rails version (previously on 5.0.5) to 5.1.4 but problem is still there :( Any idea ? Thanks

Stephane Le Boisselier

I solve this doing :

var token = $('meta[name="csrf-token"]').attr('content');
xhr.setRequestHeader("X-CSRF-Token", token);

But I don't understand why xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken()); is not working.

Other question, How do you do to have the full url image in src ? I only have /uploads/blablabla, and I have to send html with my api to a mobile app so, I need the full url.

Thanks for your help

Stephane Le Boisselier

Done with :

shrine_options = {
host: ""

Shrine.storages = {

cache:"public", prefix: "uploads/cache", **shrine_options),
store:"public", prefix: "uploads/store", **shrine_options),

In development on cloud9 my trix editor work well, but in production on Heroku, i cannot write on the text area. Anyone know how i can fix this issue?

I tried to combine this with the direct S3 uploads and keep the URL's private. It's working well for me so far so here are the changes i made in a gist
I am a relative novice in Javascript so if anyone has corrections or improvements I would love to know :)

Thanks for sharing Neil!

I really need help with trix, i dont know what iam doing wrong, but Trix isnt working for me in Rails 5.2.
I did everything like in the setup explained but i had my postmodel before.
so as you can see i have a field called t.text "content" - and everywhere trix is referring to a body. Is that the issue? How can i change the migration so that my content is a body? And! If that even needed? I mean if i switch in my code body for content it is supposed to work aswell right?

My Schema looks like this:
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.index ["slug"], name: "index_posts_on_slug", unique: true

I wish I could help but I don't know the answer. Why don't you try the GoRails Slack?

How can this been done for live direct upload? I watched the aws direct videos but my JS skills arent strong enough to get it to work

I'm getting a Javascript error saying the variable Trix is not defined when trying to disable captions and file size display. Any ideas?

Make sure you import Trix in your JS.

Thanks for the quick reply.

I'm pretty certain it is importing, I see the link in the head.

Still haven't been able to get this working and wanted to provide a bit more detail.

In my application.js I do have //= require trix and I can see the file in the head of the page; however, it does not look like the same file that appears on It seems mostly the same, but if I do a search in the files for the keyword "config" I get 47 matches in the file on my app and 56 in the file on

Could this be a versioning issue?


We have the photo uploads working now (THANK YOU CHRIS FOR A GREAT TUTORIAL!), but unfortunately, there is no 'drag and drop' option on mobile, so it means only those users on desktop can add a photo to their posts. I've been searching on google for a tutorial on how to add a custom button to the Trix editor.

Any thoughts? Has anyone done it before?

Has anyone tried saving a reference to to the Photo record within the post.body, rather than the URL itself?

I think that's how Action Text does it when using Active Storage. They include the Global ID ( gid://app/Photo/123 ) instead of the URL of the image itself. Then, when the post.body gets rendered you're free to display it anyway you want.

ActionText uses attachable_sgid from the Attachable concern. That's covered in the @mentions in ActionText video on how that works.

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 20,000+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.