Active Storage integration with Google Cloud Storage — Fast-Track

Felipe Bohorquez
Oct 22, 2019 · 7 min read

Today we’re going to talk about how to setup Google Cloud Storage to host images on your Rails app. This builds from my experience hosting pictures for Uff! a Ruby on Rails web app to discover street artists.

Image for post
Image for post
Uff Home Screen — With Active Storage + Google Cloud

Note: While reading this walk-through feel free to reference the source code and deployment to see the results in action.


Active Storage Setup — Quick Reminder

You need to have Active Storage in place for Google Cloud Storage to work. If you don’t have Active Storage installed make sure you do rails active_storage:install and rake db:migrate so you can get the Active Storage tables for file management as well as the storage.yml configuration file that will be essential for Google Cloud Storage (GCS) integration.

You will also need to add either the has_one_attached :image_file or has_many_attached :image_filesmacro for the Model that you have files associated. In the case of Uff, our Wall modelhas_many_attached :images and this will ensure that walls could have many images associated to it.

The rest of it should sound familiar as you now automagically have access to file-type model attributes that you can create, edit and delete. So since you now have a new file-type attribute you need to permit it on your controller and add it to your form views, through an image_tag and then boom your images are displaying on your local!

Before Moving Forward: Please read Active Storage Documentation. Is a great resource with examples of how to set associations, views etc. There are many other tutorials out-there but there’s no substitution to Ruby on Rails Guide so go there if you cannot have your images to display on local!


Setting Up Google Cloud Storage

As I was happily adding art walls on Uff, I noticed that my app was getting bulky in size and the server was giving a lot of responsibility of just dealing with images. Of course Uff lets you discover art so at some point in production server bandwidth could be affected on just displaying and hosting images. Both AWS and GCS do a great job serving and hosting files. So let’s leave it to them to do take all the load, we’ll just write and retrieve our files from their servers ;)

To start, let’s go ahead and add gem “google-cloud-storage”, “~> 1.11”, require: falseto our Gemfile and then run bundle install.

Now if we go to config/environments folder we’ll see the same line in both our production.rb and development.rb files: config.active_storage.service = :local

This pretty much is telling us that all our files are being stored locally. Let’s change development.rbline to say :google_dev so it will now read as:

config.active_storage.service = :google_dev

Note: In production.rb you should use just :google instead.

Configuring our Google Cloud Storage (GCS) Account -Skip if Already Done

Feel free to skip this section if you already done it.

Before we move forward let’s ensure you have your GCS account setup. You can create one for free and get some trial credits for free as well.

Once your account is setup. Go ahead to and create a New Project and give it a name. The home screen is overwhelming but we only need to add a storage bucket, let’s just click the hamburger menu and click Storage:

Image for post
Image for post

Once in there let’s click on Create a Bucket. Give your Bucket a name, select your preferred region and select Standard for Storage Class. You should leave all other options as default.

Now we need to create some credentials so our Rails app can communicate with GCS. Generating a Service account key will facilitate this. Let’s give it a name and we can set the role to Storage Admin or Owner. Then lets ensure we are saving as JSON file. Steps to do that below.

Image for post
Image for post
Image for post
Image for post
Image for post
Image for post

Once saved to your computer GCS will warn you how this key “allows access to your cloud resources, so store it securely”, its totally true! Also feel free to rename with a nicer name it so you can refer to it later.

Once renamed you can add this key to your configfolder. If you’re saving to your repository ensure you’re not tracking it by adding the location to your .gitignore.


GCS: Uff We Go!!

Before rolling up the sleeves: If you don’t have dotenv gem, make sure you do so now! Add gem “dotenv-rails”, “~> 2.7” to your Gemfile then bundle install . Then create a .env file in your root folder, and add *.env to your .gitignore, we’ll be using this file later!

Note: We recommend you testing GCS on a development environment before testing GCS on production.

We can now go to config/storage.yml and configure it for GCS use. You use your own project and bucket name. Below is the code as if we were using both production and development GCS.

google_dev:
service: GCS
project: MyApp-123456
credentials: <%= Rails.application.credentials.gcskey.as_json %>
bucket: test-434
google:
service: GCS
project: MyApp-123456
credentials: <%= Rails.application.credentials.gcskey.as_json %>
bucket: test-434

For production lets us use Rails Credentials. Using Rails credentials lets us add a hash instead of the path and is as easy as making a new hash on your credentials. To do this we need to modify our config/credentials.yml.enc file. In terminal type the following command (note: I’m using VS Code, but you can replace the EDITOR= to vim, atom, etc):

EDITOR="code --wait" rails credentials:edit

This will open up the file in VS Code and all you have to do is set a hash. Let’s name our hash for this example as ‘gcskey’ and equal it to the contents of the JSON file we downloaded earlier:

gcskey: #JSONcontents

You can now save your file and you should have GCS ready for production! You can always puts Rails.application.credentails.gcskey on console to ensure it was saved correctly.

I recommend using Rails Credentials on both. However, for development another way to do it is to go to our .env file and set the GOOGLE_APPLICATION_CREDENTIALS= to the actual path of our JSON file. In development our .env file should look something like this:

GOOGLE_APPLICATION_CREDENTIALS=/Users/Owner/Documents/MyApp-123456/config/gcskey.json

If you used environment variables for development you also need to change your storage.yml to:

google_dev:
service: GCS
project: MyApp-123456
credentials: <%= ENV['GOOGLE_APPLICATION_CREDENTIALS'].to_json %>
bucket: test-434

Stuck? You can read more about Rails credentials here.


Using GCS in your Rails App — Fast-track (Public Access)

Now we are ready to store our images in GCS and read from them! Yay!

Go ahead an try to add a picture. If everything went fine you should see in your console a confirmation message in green such as:

GCS Storage (233.2ms) Uploaded file to key: 45l9tmnypxrhvuj935cq1ip7fj1 (checksum: 4443kfjfFFjdjdjfkdl==)

Errors will be displayed in red and usually means there’s a problem in reading the key you provided.

You might actually find that storing to GCS is pretty straightforward but only if you did the setup correctly.

Now regarding displaying our images, there are many ways to setup your GCS console and read your images from your bucket. Here I’ll be showing you a quick way to read from GCS. Ready?


Cool. Let’s go back to our GCS console and the bucket we created. We need to add a view permission level.

Click Permissions, Add Members, select allUsers and the role of Storage Object Viewer.

Image for post
Image for post

Yes this will make our bucket public, but it will also make accessing our images in our views pretty straightforward.

Now since you already added a picture you should see it in the bucket. Notice the image name change?

Image for post
Image for post

This is the key that was given to our image and how we would handle displaying it in our views. GCS has an entry point for all public buckets that go like this:

https://storage.googleapis.com/your_project_name/image_id

Go ahead and manually replace the URL above with your project name followed by the image id. Voila! Your image is retrieved!

Image for post
Image for post

Now lets go back to our views since we are using Active Storage we can call the .key method and it will give us the key that was given! This is how it will look in regular html image tag:

"<img src='https://storage.googleapis.com/#{project_name}/#{image.key.to_s}' alt='Wall image'>"

If everything went find you can go ahead and reload and voila you have an image from GCS on your Rails App! See screenshot from Uff below:

Image for post
Image for post

That’s all. Go ahead and embrace that good feeling then add images away!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store