Rails 6 Action Text Amazon S3 Images and Attachments not Uploading

ruby on rails web development software development

So we've finally taken the plunge and carried out our first Action Text implementation. It was used to power a blog.

But we ran into an issue.

Problem

Here are the symptoms

  • We were on Rails 6
  • We had Active Storage setup
  • We had Action Text setup
  • On development, we used 'file' for Active Storage and it worked perfectly
  • On production, we used 'S3' for Active Storage and it didn't work
  • We tried switching to 'S3' for development to debug and it still didn't work

What was weird, is we were seeing things like this messages like S3 URL generated complete with an AWS Key, but when we went to browse the Amazon S3 bucket, there was nothing.

There was also something weird happening with the rich text editor. When we selected an image - we would see this gray bar across the image (that should have been the clue:)).

Solution

After days of trying to figure out what was going on, we stumbled upon this post which had our solution: https://stackoverflow.com/questions/63998547/rails-action-text-no-upload-after-switching-to-amazon-active-storage.

So as it turns out, Action Text and the Trix Rich Text Editor use client-side direct uploads. If you're not familiar with this, basically the file gets uploaded directly from the browser to the Amazon S3 without going through your Rails server. When you do a web request from a browser to another site, in this case from the user's browser to Amazon S3, you have to set up CORS rules!

So the answer, is you have to set up some CORS rules like this:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT"
        ],
        "AllowedOrigins": [
            "https://www.example.com"
        ],
        "ExposeHeaders": []
    }
]

Ensure you actually fill out the Allowed Origins to match your actual website. If you're doing dev testing on your machine, you can put http://localhost:3000.

By the way, if you're wondering what that gray bar was all about? That was the progress bar for directly uploading to Amazon S3. It stayed there because the web app didn't have the CORS permissions to write to Amazon S3.

Thoughts

Unless I missed something - which is very possible - I think the main issue here is the documentation for Action Text. Active Storage can be set up in multiple ways. For example, you can set up Active Storage WITHOUT direct uploads and it'll work fine. However, to use Action Text, you HAVE to set up direct uploads. At the time of the writing of this article, this is all they have "Also, you need to set up Active Storage for embedded images and other attachments. Please refer to the Active Storage Overview guide." What they probably should say is that if you're embedding images or other attachments, be sure to setup "direct uploads", which subsequently tells you how to setup CORS.

Alright, hope that helps out some peeps!

Casey Li
CEO & Founder, BiteSite

Introducing Trello Views!

custom software trello software development

So we use Trello - a lot.

We use it to manage our Scrum Express process and it's become an integral part of our software development. However, one thing we noticed is that our Trello boards are getting BIG. Like super wide with lots of columns.

The thing is though, at any given time, we only need to see a subset of those columns. For example, when doing Product Management meetings, we're concerned with a very different set of columns than when we're doing development.

So - we built a Chrome extension to solve this. We call it Trello Views.

Super MVP at this point, but would love some feedback.

Check it out:

https://chrome.google.com/webstore/detail/trello-views/ljfoaeaaojcefkmljglbbphcoclnodnm

Casey Li
CEO & Founder, BiteSite

Carrierwave-AWS and fixing Excon::Errors::SocketError Broken Pipe Errors

custom software ruby on rails software development

So we've been using Carrierwave for a while. It's an amazing solution for Ruby on Rails apps that need to store files.

We use it mainly with Amazon AWS S3 as our storage. However, recently when trying to use it for a new app, we kept running into these errors anytime we tried to upload anything to S3. The errors were Excon::Errors::SocketError Broken Pipe errors. Most posts on the internet suggest issues with permissions or with not setting the region properly, but after trying all those, we still couldn't get it to work.

We then came across a Stack Overflow answer that talked about using an alternative gem called Carrierwave-AWS.

I was skeptical at first, because I wasn't sure who was maintaining it and why I hadn't heard of it before. As it turns out, this is maintained by the same people who maintain the original CarrierWave!

This new library uses the official AWS-SDK library and actually solved my Broken Pipe issues! What's more, I was happy to see that I could still revert to using file storage for dev environments with this library. All pretty sweet!

So if you're using Carrierwave with AWS S3 and you haven't heard of Carrierwave-AWS, it's probably a good time to check it out!

Here's the link: https://github.com/carrierwaveuploader/carrierwave-aws

Enjoy!

Casey Li
CEO & Founder, BiteSite

Ruby on Rails Templates

ruby on rails software development

As a junior Ruby on Rails developer, GoRails has been a great help with all their free video tutorials Chris Oliver creates. When I started to venture into rails templates, I found he hosts a repository of community created rails templates for others to upload or use for free.

Check it out here if you're a Rails developer and are interested in automating some of your workflow. https://railsbytes.com/

Chris Francis
Software Developer, BiteSite

Ruby on Rails CSS File Structure

css ruby on rails software development

Ruby on Rails is an amazing framework. At BiteSite, we started using it back in 2011 and haven’t stopped since. It’s combination of technical ability and software philosophy has kept it our framework of choice when it comes to web development and it only gets better with time.

One of the things we appreciate most about Ruby on Rails is its convention over configuration philosophy. In short, it basically says, “If you follow our conventions, you don’t have to configure your code”. This allows for less boilerplate code and is, in my opinion, the best way to enforce coding conventions.

With convention over configuration, one of the best benefits you get is a well designed architecture for your code. Every Rails app puts all of its controllers in the same folder, all of its models in the same folder and so on. It makes developing Rails so easy to jump into.

That being said - it’s not perfect. While convention over configuration is in so many places in Ruby on Rails - there are areas it doesn’t exist and you’re left to come up with your own design or structure.

One of these places is CSS.

While Rails does suggest how to structure your CSS when you use scaffolding, it doesn’t really have a strict convention over configuration policy about how to split up your CSS into multiple files and where to put them (aside from the ‘stylesheets’ folder).

When apps get big, this can become a problem.

Over the years, we have come up with a system that has served us pretty well that we thought we’d share. It’s not perfect, but it does work.

Definition

To be clear, this system only dictates how to split up your files and where to put them. It does not cover how to actually structure your CSS selectors and CSS code within those files.

Driving Forces

When we set out our to improve our CSS File structure, there were really two driving forces. One, as with most coding, we wanted our code to be DRY (Don’t Repeat Yourself) where possible. Now, notice I said “where possible” vs. “as much as possible”. We found that overtime, it was hard to keep track of CSS code and so many times you would change some CSS code to fix one problem, but not realize it was being used in 5 other places. We were consistently breaking pages without realizing it and so we implemented our second driving principle: make our file structure easy to follow and easy to figure out what pages it was affecting.

We realized this was breaking DRY code, but it kept our codebase sane and predictable.

(Incidentally, we found out later on, that this true separation of concerns vs separation of technologies was being embraced in future frameworks like React and Vue where you can scope CSS to individual components).

SCSS vs CSS

Note, at BiteSite, we use SCSS to help with a lot of this, but a lot of the learnings can be applied to vanilla CSS.

CSS File Structure

With those two driving forces in places, we came up with the following CSS file structure:

app
↳ assets
  ↳ stylesheets
    ↳ base
    ↳ common
    ↳ components
    ↳ views

The 4 folders we’ve introduced are base, common, components, views. Let’s explore each of these.

base

The base folder is where we put our UI Kit CSS. So all your standard buttons, links, typography, tables and other CSS that would apply to most or all web apps we put in here. To complement this, we also include things like globals and colorswatches which we can import into the rest of the files. We’ll usually split each of these into its own file. Examples include:

app
↳ assets
  ↳ stylesheets
    ↳ base
      ↳ globals.scss
      ↳ colorswatches.scss
      ↳ buttons.scss
      ↳ links.scss
      ↳ typography.scss
      ↳ forms.scss
      ↳ tables.scss

common

The common folder is how we achieve ‘DRY’ code outside of UI Kit elements. While we generally try to scope our CSS to specific pages (or components if using React), there are definitely some cases where it’s better to re-use CSS within HTML/JS code. We have a dedicated folder for these to help remind developers. It tells the developer, “Hey, if you’re editing something in the common folder, be careful, because it most likely affects more than just the part of the web app that you’re working on.” Additional to some reusable CSS that’s specific to your app, we also include things like layout CSS here. Examples include:

app
↳ assets
  ↳ stylesheets
    ↳ common
      ↳ layout.scss
      ↳ shopping_cart_line_item.scss
      ↳ pricing_badge.scss

components

This is specific to web applications that use Webpacker + React. If you don’t use React, you can skip this part. When we create components and want to scope some CSS specifically to the component. Now I’m sure there are better JS ways to do this, but to be honest we haven’t quite figured them out yet, so we do this instead.

To make this work, we add a CSS ID/class selector to the outer most element of the component that starts with “component-”. Here is an example:

/* product_card.jsx */
…
function ProductCard() {
  return (
    <div className=’component-product-card’>
      …
    </div>
  );
}

Then we place it’s corresponding CSS in this folder:

/* app/assets/stylesheets/components/product_card.scss */
.component-product-card {
  …
}

views

This is the last folder and we use this for page specific CSS. To do this scoping, we surround every view template in a <div> or <span> that has an ID in the form of “controller-view”. Here is an example:

<!-- app/views/products/show.html.erb -->
<div id=”products-show”>
  ...
</div>

With the page scoped, we then place the CSS files in a file structure that’s similar to the regular app/views/ folders. We create a folder for each controller and a file for each view.

/* app/assets/stylesheets/views/products/show.scss */
#products-show {
  ...
}

Conclusion

We’ve been using this file structure for over 5 years now and while we know of some shortfalls (e.g. React components named the same but within different folders), it has worked out very well for us. Hopefully this will help others as well!

Casey Li
CEO & Founder, BiteSite