A thoughtfully designed template for building modern Rails apps 🔥
Get started on your new app within minutes instead of hours 🚗💨
To get going clone this repository and perform the following steps:
- Run
rails credentials:edit
to re-generateconfig/master.key
and createconfig/credentials.yml.enc
. - If your application requires
ActiveStorage
, runrails active_storage:install
to generate a migration that creates the necessary tables. Userails db:migrate
to run the migration. - You can now run
bin/configure
, which will help you in configuring the template.
As an alternative to running the script you can perform all of the following steps manually.
- Change application name in
config/application.rb
. - Update
database.yml
to reflect the new application name. - Update
TODO
items inconfig/environments/production.rb
. - If you plan on using Figaro, copy
config/application.yml.example
toconfig/application.yml
. - ESLint is preconfigured for modern JS with React support (AirBnB styleguide).
If you want to use it install packages with
npm install
/yarn [install]
, otherwise remove.eslintrc
andpackage.json
. - If you don't plan on tracking the template, you can remove the remote, otherwise rename it and
add your new remote as appropriate.:
$ git remote rename origin rails_new $ git remote add origin ...
- If you want to use AirBrake, make sure the following 2 environment
variables are set:
AIRBRAKE_PROJECT_ID
AIRBRAKE_API_KEY
- New Relic is pre configured in
config/newrelic.yml
, but you need to comment in the environment variables for it work on Heroku (lines 10 and 17). - The app is preconfigured for Google Analytics, just add
GOOGLE_ANALYTICS_ID
to the environment. - We prefer to use vanilla Sidekiq for worker/queue management. If you prefer to use ActiveJob please see the configuration/options that were removed in 59cf38d.
Variable | Comment |
---|---|
AIRBRAKE_PROJECT_ID | Used in config/initializers/airbrake.rb |
AIRBRAKE_API_KEY | Used in config/initializers/airbrake.rb |
BLOCK_HTTP_TRACE | Disables HTTP TRACE method if set to true/t/1 |
BUNDLE_GEMFILE | Useful when using a Gemfile.dev |
DATABASE_URL | Used for production env, automatically set by Heroku |
GOOGLE_ANALYTICS_ID | Will be added to the main application layout if set |
HOST | Your base URI, e.g. https://myapp.herokuapp.com |
NEW_RELIC_APP_NAME | Used in config/newrelic.yml |
NEW_RELIC_LICENSE_KEY | Used in config/newrelic.yml |
PORT | Port Puma will listen on, defaults to 3000 |
RAILS_LOG_TO_STDOUT | Set by Heroku Ruby buildpack, set manually on other platforms if needed |
RAILS_MAX_THREADS | Number of Puma threads, defaults to 5 |
REDIS_URL | Used in config/cable.yml |
WEB_CONCURRENCY | Number of Puma workers. We default to threads only, no workers |
All of the following have been installed and pre-configured:
- Rails 5.2.0
- Ruby 2.5.1
- pg for
ActiveRecord
All of these are managed by yarn
.
- Brakeman
- bullet
- letter_opener
- memory_profiler
- newrelic_rpm
- nullalign
- pry
- pry-byebug
- pry-doc
- rack-mini-profiler
- RuboCop
Rspec has been preconfigured for Rails 5.1+ system tests.
- No need to
require 'rails_helper
, we do it in.rspec
- bundler-audit (runs on CircleCI)
- capybara
- factory_bot_rails
- shoulda-matchers
- spring-commands-rspec
- webmock
The following default Rails gems have been removed:
By default ES6 will not work for files in app/assets/javascript
since Uglifier will fail to
process them. This is why we applied the following change to config/production.rb
, which allows
you to use ES6 project wide:
- config.assets.js_compressor = :uglifier
+ config.assets.js_compressor = Uglifier.new(harmony: true)
Also note that for everything to work properly on Heroku, you need to set up your buildpacks like this:
heroku buildpacks:clear
heroku buildpacks:set heroku/nodejs
heroku buildpacks:add heroku/ruby
ApplicationDecorator
: lightweight alternative to Draper or similar gems.ApplicationForm
: Minimal form class based onActiveModel
.ApplicationPresenter
: a subclass ofApplicationDecorator
for presenters, includes tag helpers.
All custom classes are fully documented with yard and come with generators.
Use yard doc
to generate documentation and yard server --reload
or yard server --gems
to start
a local documentation server.
If you want to add specific gems for development that may not be interesting for other developers,
you can add a Gemfile.dev
(ignored by our .gitignore
). Gems listed there can be installed with
bundle install --gemfile Gemfile.dev
and the resulting lock file is gitignored too.
Example Gemfile.dev
:
source 'https://rubygems.org'
eval_gemfile 'Gemfile'
gem 'awesome_print'
The eval_gemfile
line will ensure that all gems from your regular Gemfile
will be included too.
The BUNDLE_GEMFILE
variable can be used to let Bundler now which gemfile to use:
BUNDLE_GEMFILE=Gemfile.dev rails c
There's a custom middleware (Rack::RejectTrace
) for completely disabling the HTTP TRACE method as
required by certain security audits. It can be enabled via the BLOCK_HTTP_TRACE
environment
variable.
Favicons were generated with Real Favicon Generator, consider using the same tool when replacing them for your project.
For those wishing to use Docker for development the whole app has been dockerized and the setup is fairly well-documented. Features:
- Images use Alpine Linux to keep their size small.
docker-compose.yml
sets up and starts Postgres, Redis, Sidekiq, Rails and the Webpack dev server.- Uses a persistent bundle cache, so there's no need to rebuild the image to add gems.
- Persistent volumes for Postgres and Redis.
- No exposed ports except for Rails (mapped to port
3000
by default)
The following files relate to our Docker setup:
Dockerfile
: main setup for theapp
containerdocker-compose.yml
: Ties Postgres, Redis andapp
togetherdocker-entrypoint.sh
: Custom entry point to facilitate bundle cachingProcfile.docker
: Used by the entrypoint script to bring up services.dockerignore
: similar to.gitignore
, specifies files we don't want copied into the container
Start the environment and build the images if necessary:
$ docker-compose up --build
Building app
[Step 1/12 : FROM ruby:2-alpine
---> 8302cc790fbf
Step 2/12 : RUN apk update && apk add --update --no-cache build-base chromium chromium-chromedriver git imagemagick libxml2-dev libxslt-dev nodejs tzdata postgresql-dev
---> Using cache
---> 9d1d0b398c26
Step 3/12 : RUN bundle config build.nokogiri --use-system-libraries
---> Using cache
---> 0a5ca06d7700
Step 4/12 : WORKDIR /app
---> Using cache
---> c61498ba7e64
[...]
Start the environment without (re-)building images (add -d
to daemonize):
$ docker-compose up
Starting rails_new_postgres_1 ... done
Starting rails_new_redis_1 ... done
Starting rails_new_app_1 ... done
Attaching to rails_new_postgres_1, rails_new_redis_1, rails_new_app_1
[...]
Stop the environment but keep the containers:
$ docker-compose stop
Stopping rails_new_app_1 ... done
Stopping rails_new_postgres_1 ... done
Stopping rails_new_redis_1 ... done
Stop the environment and remove the containers:
$ docker-compose down
Stopping rails_new_app_1 ... done
Stopping rails_new_postgres_1 ... done
Stopping rails_new_redis_1 ... done
Removing rails_new_app_1 ... done
Removing rails_new_postgres_1 ... done
Removing rails_new_redis_1 ... done
Removing network rails_new_default
Execute a command inside the app
container:
$ docker-compose exec app ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-musl]
Execute a command inside the app
container that needs env variables:
$ docker-compose exec --env RAILS_ENV=test app rails db:setup
Created database 'rails_new_test'
-- enable_extension("plpgsql")
-> 0.0251s
-- create_table("users", {:force=>:cascade})
-> 0.0366s
Adding a new gem (does not require image rebuild):
# update Gemfile
$ docker-compose exec app bundle
Running specs:
$ docker-compose exec app rspec
....................
Finished in 0.47352 seconds (files took 16.36 seconds to load)
20 examples, 0 failures