Using Cloud Services with a Rail App

Deploying a Rails app to production and making use of Google Cloud products to keep things scalable. We can use Kubernetes or AppEngine to host the app itself, Cloud SQL as the database, and Google Storage for ActiveStorage. Each of these products can scale based on need, creating new compute instances to handle traffic, adding storage space to the database automatically, and storage buckets that can handle anything.

Google Storage

  • Create a storage bucket
  • Create API Credentials Service Account

Config

#/config/storage.yml
google:
  service: GCS
  project: <project-id>
  credentials: <%= ENV['GOOGLE_APPLICATION_CREDENTIALS'].as_json %>
  bucket: bucket-dev
google_dev:
  service: GCS
  project: <project-id>
  credentials: <%= Rails.root.join("soundtracker-creds.json") %>    # Link to creds file
  bucket: bucket-prod
# config/environments/development.rb
config.active_storage.service = :google_dev
# config/environments/production.rb
config.active_storage.service = :google
echo "
gem 'google-cloud-storage'
gem 'activestorage-validator'" >> Gemfile

bundle install

Setup

Add the ActiveStorage requirements to the model and the view:

# model/
# add the has_many_attached field at the top:
class Sound < ApplicationRecord
  has_one_attached :thumbnail
  has_many_attached :sound_clips
  belongs_to :user

  # Add the validator:
  validates :sound_clips, presence: true, blob: {content_type: [ 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/mpeg3', 'audio/x-mpeg3', 'audio/mpg', 'audio/x-mpg', 'audio/x-mpegaudio' ]}
end

# view
# add the form field at the bottom:
<div class="field">
  <%= form.label :sounds %>
  <%= form.file_field :sound_clips, multiple: true %>
</div>
# controller
# add the required param to the bottom:
def sound_params
  params.require(:sound).permit(:location, :description, :name, :thumbnail, sound_clips: [])
end

Google Cloud Sql

Setup

gcloud services enable sqladmin.googleapis.com
gcloud sql instances create soundtracker-production --database-version=POSTGRES_11 --tier=db-f1-micro --region=us-central1 --assign-ip

gcloud sql users set-password root --host % --instance soundtracker-production --password <pw>

gcloud sql users create worker --instance oundtracker-production --host % --password <pw>

Proxy

For testing locally, we need Google’s proxy to allow easy connections to the CloudSQL instance.

curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
chmod +x cloud_sql_proxy
sudo mkdir /cloudsql && sudo chmod 777 /cloudsql
./cloud_sql_proxy -dir=/cloudsql -credential_file=sql-creds.json

Config

#/config/database.yml

production:
  <<: *default
  database: photo_album_production
  username: prod_db_user
  password: ENV[DATABASE_PASSWORD]
  socket: "/cloudsql/<project_id>:us-central1:photo-album-production"