Configuring your Rails backend app to get a blob from your vanilla js frontend single-page app to Google Cloud storage
By: Sharad Satsangi
Tags: Rails, Google Cloud Storage, Carrierwave, JavaScript

Configuring your Rails backend app to get a blob from your vanilla js frontend single-page app to Google Cloud storage

For a bootcamp project my teammate and I came up with a fun idea. We’d decided to hack together a multitrack audio recorder. We looked at some sweet documentation on MDN and it seemed like, even though we’d have our work cut out for us, we’d found the libraries that would work. Since we were working with audio files, we thought it would be great to have some sort of cloud storage solution worked out instead of saving the stuff locally. I‘m really interested in cloud services so I jumped at the chance to get our project working with Google Cloud. It was a huge learning experience, here are some of the takeaways I have from the experience that you might find helpful, too!

That one cloud looks like Object Storage that’s Secure, Scalable, and Durable! The other one looks like Moomin.

The Big Picture

In our frontend app, we stored media streams accessed through Javascript’s Mediarecorder object as blobs. We sent the blobs as raw form data to Rails, where the controller created a new gCloud object containing metadata about the file, including the link where the file will be stored in cloud storage. After successfully creating the gcloud object, the controller used the carrierwave gem to send the object to the local model and to send the blob itself to cloud storage.

An overview of cloud storage implementation

Set up the backend part 1

We were relying on a Rails server with SQLite. Be sure when you set up the rails server to set it up as an api:

rails new my-app-backend --api

In the gemfile, add gem ‘gcloud’ . The gem is for everything cloud services offers and is huge, so be prepared to wait when you bundle install .

While you test this locally, be sure to uncomment the gem ‘rack-cors’ line in the gemfile and uncomment the code in initializers/cors.rb .

Set up Google Cloud

Set up an account with Google cloud. The free tier was plenty big for my needs. I was surprised at all the cloud services they let people play with for free, there’s more fun to be had here. When you set up Cloud Storage, set up a project and a bucket. Buckets are where files get written to and read from, so be sure to set the privs. The best way to secure access for rails is by creating a service account and key. The documentation linked here is really top-notch, go and visit the docs, they walk you through with very friendly graphics. Follow their recommendation and choose a JSON certificate. Put it in a directory in your backend and go ahead and add it to your .gitignore right away so you don’t upload that certificate to github. Also, don’t forget to include that gcloud gem in your gemfile !

After this, figure out your strategy for file management in rails.

… or at least check out Active Storage first!

(DON’T) Set up Carrierwave

So, it’s my first time and I hastily chose the solution of using Carrierwave with Rails. If you are still in the assessment stage, Rails 6 has ActiveStorage and it looks really well supported and documented. However, if you’ve already committed to Carrierwave here’s what I can say about some of the curveballs:

Use the carrierwave google storage gem. gem ‘carrierwave-google-storage’ in your gemfile.

in your gemfile. Use an environment variable to point to the service key . I set GOOGLE_APPLICATION_CREDENTIALS to the path for my service account key. It was recommended by carrierwave to set env var’s for the bucket and the project name, but I was having trouble getting those to work properly and decided to forego the potential security issue since it was a class project and not going live.

. I set to the path for my service account key. It was recommended by carrierwave to set env var’s for the bucket and the project name, but I was having trouble getting those to work properly and decided to forego the potential security issue since it was a class project and not going live. The config/carrierwave.rb file — The documentation I found had some extra stuff, but I got things working just setting the config:

It looked kinda like this

Set up an Uploader for Carrierwave Generate an uploader for the data model that will hold the links to google cloud by rails generate uploader ModelName . The only line I had in the uploader class in app/uploaders/carrierwave.rb was storage :gcloud . In app/models/model_name.rb , add the line mount_uploader :string_field_name, ModelNameUploader

Generate an uploader for the data model that will hold the links to google cloud by . The only line I had in the uploader class in was . In , add the line In your model_name_controller.rb all the commands you’ll need to insert the blob into the bucket and have the info available in your db will look something like this:

Please note the project name has a string of numbers after it. This is the project string that appears in your service key. Google will require you to use your projectname as it appears in that key.

… still with me? Great! We are done with the backend!

POSTing the blobs from the frontend

There was one other issue that we had, passing the blob from the frontend to the backend via fetch. Thanks to Dakota Lillie, a total saint, for this blog, which laid out the secret sauce quite clearly. Pass the blob as formdata, don’t use headers, don’t use stringify.

The first argument to the append is what rails will use as the key in your params. The second argument is the blob, the third argument is an optional filename.

No headers, No Stringify, No Problem!

It was tempting to use a friendly filename instead of a randomly generated one, but Google has some strict requirements for what can be a filename in the bucket. I found it easier to add an extra field to the data model to handle friendly names.

References/Recommended resources: