# Rails on App Engine: Tips and Tricks

> Last updated: 2017-03-09

At last year’s Rails Conference we announced the beta of [Google App Engine](https://cloud.google.com/appengine/docs/flexible/ruby/) for Ruby. Today we announced that [App Engine Flex has gone GA](https://twitter.com/googlecloud/status/839901710948589568). As we have gotten closer to GA, I’ve built a few non-trivial Rails applications and deployed them to GAE. I’ve also given some one-on-one help to others deploying to App Engine or Google Cloud for the first time. In this process, we’ve found and fixed a few bugs, and I’ve built a list of common things that trip people up on their first deploys.

## Basic Architecture and Gems Used

I’ve worked on two main sites during the last six months. One is for a local non-profit. The other, [Tind-Purr](https://catornot-159718.appspot.com) is for a demo and my amusement. Both applications are using Ruby 2.3 and Rails 5. Both applications have a MySQL database. Tind-Purr uses SQLite for Dev and Test and Cloud SQL in production. The non-profit wants to maintain their own database for production but uses Cloud SQL for Staging.

User uploaded images are central to both websites. I’ve used [Paperclip](https://rubygems.org/gems/paperclip) to support file uploads with both apps. I chose Paperclip because I had used it before. Tind-Purr stores images in [Google Cloud Storage](https://cloud.google.com/storage/) using Fog and the [Fog-Google](https://rubygems.org/gems/fog-google) gem.

Tind-Purr has some simple background task processing. I am using ActiveJob with [Google Cloud Pub/Sub](https://cloud.google.com/pubsub/docs/overview) as a backend. The background task is designed to feed a queue of “pictures that need votes” for the frontend, so it needs to run after every upload and on a regular interval as well.

The non-profit website required authentication, roles, and an admin interface. Authentication was done with [Devise](https://rubygems.org/gems/devise) again because I had used it before. Roles and authorization are implemented with [CanCanCan](https://rubygems.org/gems/cancancan), the successor to CanCan. [RailsAdmin](https://rubygems.org/gems/rails_admin) is my go-to for quick and dirty admin interfaces. I also needed to support payments and did that with Stripe.

On the frontend, the non-profit requested that I use Bootstrap. I used Materialize for Tind-Purr. In both cases, I used [SimpleForm](https://rubygems.org/gems/simple_form) because CSS is not my strength.

## Common Gotchas

To use App Engine, you will need two things: A Google Cloud account and the Google Cloud SDK. Once you’ve taken care of these two pieces, you can navigate to your app directory on your dev machine and type `gcloud app deploy` to start your first deployment. `gcloud` will analyze your directory structure and ask you to confirm that you have a Rails application. Then it will write out a file called `app.yaml.` that configures the App Engine settings for your application.

### Database Creation and Migrations

For folks who are used to other cloud providers, the way Google handles database tasks is a bit different. To run any of the `rake db` commands for production, you must connect your dev environment to the production database by doing `RAILS_ENV=production rake db:[create|migrate|seed]`. This means you have to do the database creation and any necessary migrations before you do `gcloud app deploy`. You also must have `config/database.yml` set up to connect to production on the machine you are using for deployment.

There are several database options available on Google Cloud. More information about those options and how to connect to Rails is available as part of our [Ruby Tutorial](https://cloud.google.com/ruby/getting-started/using-structured-data).

### Environment Variables

The most common issue I’ve seen with App Engine Rails deployments is people who forget or don’t know how to set `SECRET_KEY_BASE` and other environment variables. If you look in your `config/secrets.yml` you will see something that looks like this:

```
# secrets.yml

development:
  secret_key_base: 2b8e0636d75c...

test:
  secret_key_base: d9d3ba88a59a...

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
```

You can set environment variables in `app.yaml`. Here’s the `app.yml` I use for Tind-Purr.

```
# app.yaml

entrypoint: bundle exec rackup -p $PORT
env: flex
runtime: ruby
health_check:
  check_interval_sec: 10
env_variables:
  SECRET_KEY_BASE: 'your_key_goes_here'
```

This is also where you can put things like API keys for third-party services and Rails configurations like `RAILS_ENV` and `RACK_ENV`. You can use different app.yaml files for different environments if you choose. Just specify the file when you deploy: `gcloud app deploy staging.yaml`.

### Assets

The last big thing that I often forget is to do my asset compilation locally before I deploy to app engine. `RAILS_ENV=production rake assets:precompile` takes care of it.

## Advantages

App Engine is a different way of running Rails Apps for me. I am used to writing deployment scripts and running them within some CI/CD pipeline. Alternatively, for little apps I’m used to just cloning the code and starting Rails. For the app I did for a non-profit, App Engine let me get my early versions up in front of customers quickly and also let me stage changes for approval when they had bugs to fix.

### Debugging

For debugging my App Engine deployments, I included the [`stackdriver` gem](https://rubygems.org/gems/stackdriver). This is a drop-in gem that automatically pushes Rails logs to Stackdriver Logging. Since the logs are in Stackdriver Logging, you get monitoring from Stackdriver Error Reporting automatically. Also, the Stackdriver gem hooks your Rails App into Stackdriver Trace as well which can be useful when debugging performance issues.

### Auto-scaling

When I got Tind-Purr spun up for the first time I sent out an email to my team requesting folks upload their cat pictures. Watching App Engine automatically scale up as more folks came online was almost magical.

I also really appreciated that the deployment was pretty easy. Once the database and assets were taken care of all I had to do was type `gcloud app deploy` and up it went. When I have an update, I just deploy again and traffic is automatically routed to the new version once it is healthy.

## Learn More

If you want to learn more about running Rails on App Engine, or on Google Cloud in general check out [this guide](https://cloud.google.com/ruby/rails/).

Please enable JavaScript to view the [comments powered by Disqus.](https://disqus.com/?ref_noscript)

 ![Aja Hammerly](/img/traditionalheadshot.jpg)

Aja Hammerly

Seattle, WA

### library\_books Series Index 

- [Developer Relations](/series#developer-relations)4
- [Machine Learning Basics](/series#machine-learning-basics)3
- [Battleship](/series#battleship)5
- [Talks I Love](/series#talks-i-love)6
- [Algorithms with Auntie Aja](/series#algorithms-with-auntie-aja)3
- [Ruby and GCP](/series#ruby-and-gcp)5
- [Playing with Data](/series#playing-with-data)3
- [Kubernetes & Rails](/series#kubernetes-rails)3
- [Learn To Code Resources](/series#learn-to-code-resources)3
- [Testing Anti-Patterns](/series#testing-anti-patterns)5
