All threads / Using the Trix Editor plus File Upload Attachments Discussion
Ask A Question


You’re not receiving notifications from this thread.

Using the Trix Editor plus File Upload Attachments Discussion

Rob Thomas ·

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.

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?

Rob Thomas ·


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.

Tim Passmore ·

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?

Alex Musayev ·

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.

Alex Musayev ·

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 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

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),

Gabriel Sigouin ·

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 :)

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?

I had the same question regarding how to get around using t.text "body" as I would also like to add trix to a preexisting project where I have used "content". Did you find an answer?

I suppose I could just do a rename_column to change content to body in the db ...

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.

How do I integrate Trix with ActiveStorage and AWS S3? Thank you!

In case somebody needs it. Here are the steps to make it work.

  1. Set up your S3 bucket. Use this CORS on the bucket:
  2. Allow List Objects, and Write Objects for the public. Not exactly safe, but it allows you to upload without presigning.
  3. Optionally add Cloudfront and allow POST.
  4. Take note of your Cloudfront URL.
  5. Add this to your application.js
  6. Change the HOST to your cloudfront URL.

Chris' code did not work for me.

This is what worked for me, given I am using webpacker:

/// app/javascript/packs/application.js
// add this line:

// now we have to add the above javascript file in
// I have included it outside the packs folder
// if you want to change the location, be sure to also change the path:

// Listen for the Trix attachment event to trigger upload
document.addEventListener("trix-attachment-add", function(event) {
  var attachment = event.attachment;
  if (attachment.file) {
    return uploadAttachment(attachment);

function uploadAttachment(attachment) {

  // Create our form data to submit
  var file = attachment.file;
  var form = new FormData;
  form.append("Content-Type", file.type);
  form.append("document[file]", file); // change to suit your circumstances!!

  // Create our XHR request
  var xhr = new XMLHttpRequest;"POST", "/documents.json", true);

    // I am posting to the doucments route - your situation may be different!

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

  // Report file uploads back to Trix
  xhr.upload.onprogress = function(event) {
    var progress = event.loaded / * 100;

  // Tell Trix what url and href to use on successful upload
  xhr.onload = function() {
    if (xhr.status === 201) {
      var data = JSON.parse(xhr.responseText);
      return attachment.setAttributes({
        url: data.image_url,
        href: data.url

  return xhr.send(form);

Enjoy! And I hope that helps.

Another possibility to add in Trix into your project is following the 2 steps in the installation guide.

Chris, How hard is that to add a html table and change the text color in the trix editor.

Hi everybody,
I'm facing an issue I'll quickly describe.
I'm using rails 6 and was using Webpack to get ActiveStorage ActionText and Trix working all togother. Everything was OK : text edit and multiple files uploading via trix. WOUHOU !!!!


Now, I going back to Sprockets. My custommer is asking me for.
So, here is what I did.

  • Checking ActiveStorage working with a simple f.file_field to upload images = OK!
  • Installed Trix with one of the existing gems. = OK for text editing :)
  • Trying to upload files with trix : KO !!


  • Why it was working with Webpack ? Is it because of the upload js file you're using in this video ? This file was present in the node_module trix but not in the gem ?
  • I've tried the file you're using but it doesn't work. I've got console error : "Uncaught TypeError: Cannot read property 'preview' of undefined" on the line "Trix.config.attachments.preview.caption = ..."
  • What gem would you use for my config : Rails6 + Sprockets ?

Can someone help me please ?

Thanks a lot.


Thanks for the episode. Trix is easy and works great but is there a way to style the images. I managed to get them to align left or right but cannot get them to float left or right with text around them.

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 69,840+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2023 GoRails, LLC. All rights reserved.