At Clutter, when a new Ruby on Rails app is setup there are a few things to do once rails new finishes.

Setup Rubocop

Rubocop is a static code analyzer for Ruby. It enforces constraints around the a ruby style guide. It is useful because it reduces friction when reviewing code around common syntactic issues (i.e. tabs instead of spaces, what type of quote to use, etc). To setup:

  1. Add gem 'rubocop' to your Gemfile and run bundle.

  2. Add a .rubocop.yml configuration to your project (these are some sample defaults):

     AllCops:
       TargetRubyVersion: 2.5.1
       CacheRootDirectory: tmp/rubocop
       Exclude:
         - Gemfile
         - Gemfile.lock
         - Rakefile
         - config/**/*
         - bin/**/*e
         - log/**/*
         - tmp/**/*
         - node_modules/**/*
         - spec/spec_helper.rb
         - spec/rails_helper.rb
     Rails:
       Enabled: true
     Style/Documentation:
       Enabled: false
     Style/FrozenStringLiteralComment:
       Enabled: false
    
  3. Run bundle exec rubocop. If things worked a few style violations appear that can either be fixed or ignored.

Setup Brakeman

Brakeman is a static security vulnerability scanner specifically for Ruby on Rails. It helps to spot dangerous Ruby code (SQL injection, remote code execution, etc.). To setup:

  1. Add gem 'brakeman' to your Gemfile and run bundle.

  2. Run bundle exec brakeman. For a clean application ‘No Warnings Found’ is expected.

Switch to RSpec

RSpec offers a syntax many Ruby on Rails developers prefer. The rspec-rails project offers a tutorial on installation.

Use Postgres

Postgres is probably the best option for any new Ruby on Rails project needing to use Active Record. For info on why see What PostgresQL has Over Other Open Source SQL Databases. To setup:

  1. Setup Postgres locally (via Brew):

     brew install postgres
     brew services start postgresql
    
  2. Add gem 'pg' to the Gemfile and run bundle.

  3. Modify config/database.yml to use Postgres:

     default: &default
       adapter: postgresql
       encoding: unicode
       pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    
     development:
       <<: *default
       database: sample_development
    
     test:
       <<: *default
       database: sample_test
    
     production:
       <<: *default
       database: sample_production
    
  4. Setup your local databases:

     bin/rails db:create db:migrate
    

Use Sidekiq

Sidekiq is a fantastic option for processing background jobs. It works as an adapter for Active Job. It can also be used to run scheduled jobs with Sidekiq Scheduler. To setup:

  1. Setup Redis locally (via Brew):
     brew install redis
     brew services start redis
    
  2. Add gem 'sidekiq' and gem 'sidekiq-scheduler' to the Gemfile and run bundle.

  3. Change the active job queue adapter in config/application.rb to use Sidekiq:

     class Application < Rails::Application
       config.active_job.queue_adapter = :sidekiq
     end
    
  4. Add a config/sidekiq.yml file with these defaults:

     ---
     :concurrency: 4
     :queues:
       - default
    
  5. Generate credentials for the sidekiq web interface:

     bin/rails secret
     EDITOR="atom --wait" bin/rails credentials:edit
    
     sidekiq:
       username: 7c90907f........
       password: 14db3d85........
     ...
    
  6. Setup an initializer to authenticate access to an admin interface in config/initializers/sidekiq.rb:

     require 'sidekiq/web'
     require 'sidekiq-scheduler/web'
    
     sidekiq_username = Rails.application.credentials.dig(:sidekiq, :username)
     sidekiq_password = Rails.application.credentials.dig(:sidekiq, :password)
    
     def match?(source, target)
       ActiveSupport::SecurityUtils.secure_compare(
         ::Digest::SHA256.hexdigest(source), ::Digest::SHA256.hexdigest(target)
       )
     end
    
     Sidekiq::Web.use Rack::Auth::Basic do |username, password|
       match?(username, sidekiq_username) && match?(password, sidekiq_password)
     end
    
  7. Mount the admin interface in config/routes.rb:

     mount Sidekiq::Web, at: '/sidekiq', as: :sidekiq
    
  8. If using a Procfile add an entry for Sidekiq:

     web: bundle exec puma -C config/puma.rb
     worker: bundle exec sidekiq -C config/sidekiq.yml
    

Use a Cache Control Header

By default a cache control header is not sent in production for assets compiled through webpack or sprockets. To fix ensure that each environment has the following (use 2 years for production, 2 days for development, and 2 hours for test):

config.public_file_server.headers = {
  'Cache-Control' => "public, max-age=#{2.years}"
}

Enable Rack Deflator for GZIP

By default GZIP is also not enabled. GZIP has some tradeoffs (i.e. it takes time to shrink files), but they are outweighed by minified pages and assets. To setup add Rack::Deflater as middleware in config/application.rb:

class Application < Rails::Application
  config.middleware.use Rack::Deflater
end

Setup Continuous Integration

Often referred to as CI, continuous integration is an automated way of running tests. Jenkins is still an option, but a few commercial options now exist as well such as CircleCI or TravisCI. Each service provides documentation on setting up.