The Next Step for Any New Ruby on Rails App
• David Feinerman Github • Kevin Sylvestre Github Twitter Home
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:
-
Add
gem 'rubocop'
to yourGemfile
and runbundle
. -
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
-
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:
-
Add
gem 'brakeman'
to yourGemfile
and runbundle
. -
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:
-
Setup Postgres locally (via Brew):
brew install postgres brew services start postgresql
-
Add
gem 'pg'
to theGemfile
and runbundle
. -
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
-
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:
- Setup Redis locally (via Brew):
brew install redis brew services start redis
-
Add
gem 'sidekiq'
andgem 'sidekiq-scheduler'
to theGemfile
and runbundle
. -
Change the active job queue adapter in
config/application.rb
to use Sidekiq:class Application < Rails::Application config.active_job.queue_adapter = :sidekiq end
-
Add a
config/sidekiq.yml
file with these defaults:--- :concurrency: 4 :queues: - default
-
Generate credentials for the sidekiq web interface:
bin/rails secret EDITOR="atom --wait" bin/rails credentials:edit
sidekiq: username: 7c90907f........ password: 14db3d85........ ...
-
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
-
Mount the admin interface in
config/routes.rb
:mount Sidekiq::Web, at: '/sidekiq', as: :sidekiq
-
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.