We use Apple mac books. Preferably 13”’ mac book pro’s or airs because for portability purposes. To install your laptop. Please checkout the chapter on new laptop setup.

Ruby / Rails version management

Versions are managed by RBENV.

Database

We use PostgreSQL as a database.s

Authentication

Devise for authentication. Sometimes with register flows, sometimes without out and only Gmail flows etc.

Authorization

We use cancancan for authorization.

ENV vars management

All the settings will always be stored in ENV variables. Make sure you have rbenv-vars installed. To enable this.We use ENV vars because its easy to use for container setups such as HEROKU. Please don’t check in your ENV vars.

Active-admin for rapid data model prototyping

We use active admin heavily its amazing to sketch out a database model quickly. We usually start by building the admin screens first, this is usually done in a couple of days. After this is done and the client is content we start focusing on the front-end.

This allows us to:

  • Deliver the back-end quickly and iterative (usually on day one)
  • Give the client the opportunity to already get familiar with the data model
  • Check if we have any fields missed

Engines

We use engines to separate out our functional domains

React / SPA

We use React only when the application requires a super responsive interfaces. If so we use GraphQL and React with Apollo and our own framework.

Use db:extras rake tasks

We use a couple of rake tasks prefixed with rebuild to:

  • Build after a clone db:rebuild
  • Rebuild the database for guard db:watch
  • Get remote production data local and rebuild and test against the current codebase rebuild:from_production
  • To get a presentable state rebuild:for_demo which can be demoed

Promote model concerns

We isolate cross-cutting model functionality into its own ActiveSupport::Concern. This promotes re-usability and cross-project sharability. It also prevents cluttering your models.

Think of legit concerns that can be applied on every model such as:

  • Followable
  • Commentable
  • Sluggable

Make sure concerns don’t leak. I.e. a concern should be standalone, reusable and strive for not needing extra methods on the model implementing the concern to work. If this is needed anyway it needs to be defined when including the model.

The public folder

  • Make sure you only check in stuff you actually need. Not for test or development.

Usage of guard *

Guard enables us to rapidly prototype new functionality, we use guard for:

  • Rapid database prototyping with active admin
  • Running tests automatically

However, we are deprecating guard because it doesn’t work well and usually build our own watchers.

Testing with Ruby and Rails

We do system and integration tests, we’re not in the cult of TDD. But we try to have high level system tests that test the system as whole. We prioritize the tests by business value. We use capybara and cypress for this. We use MiniTest for the the tests:

Some sample tests are:

  • Book a table test
  • Password retrieval test
  • E-mail deadline reminder tests

You can find more on testing here.

Continuous integration

We use continuous integration for our test suite. Every push/pull-request is being checked against our test suite.

  • rake test to check for tests
  • bundler-audit on every build to check for reported vulnerabilities
  • brakeman to check for obvious code leaks
  • simplecov for checking for code coverage misses

When a build on master is done, it automatically published that version on the staging Heroku. Every other branch is not pushed.

Rule of three for refactoring

Before starting to refactor. Think of YAGNI, and follow the rule of three. Don’t prematurely refactor. Rule of three (computer programming) - Wikipedia

Working with HTML

We use SLIM for writing our HTML. This allows us to deliver sites fast.

Use of the command pattern

We use the command pattern to separate thing from the controller. The commands are our entry point to our business.

Circle CI settings

Some circle CI settings

general:
  artifacts:
    - "docs/"
    - "coverage/"
machine:
  environment:
    DISABLE_SPRING: 1
    DOCIFY: md
    SECRET_KEY_BASE: XX
test:
  post:
    - bundle exec bundle-audit update
    - bundle exec bundle-audit check
    - bundle exec brakeman -z
deployment:
  staging:
    branch: master
    commands:
      - git push -f [email protected]:my-staging.git $CIRCLE_SHA1:refs/heads/master
      - heroku pg:reset DATABASE_URL --confirm my-staging --app my-staging
      - heroku run rake db:migrate db:seed --app my-staging

Things concerning gems and our policy

We try to prevent including gems and be as conservative as possible. When including external gems in our projects please consider that these need to be maintained, kept secure and up to date and probably contain bugs.

Adding a new gem to an ruby project

When you’re adding a new gem be aware that:

  • You need to make sure that you upgrade the gem, more things can break.
  • You are increasing the attack vector, the gems might be vulnerable or its dependencies might be vulnerable.

When adding a gem, please announce it in your pull request, and announce it in the SLACK room and make sure the is OK with this.

Please make sure that:

  • The gem really adds value, its something you cant do yourself. Or its more secure. For instance device/clearance vs rolling your own.
  • The gem isn’t bloated for the problem your trying to solve.
  • The gem is maintained.

When using a gem from source

Fork a gem when using a fork from source (i.e active Active-admin). We use bundler-audit for our gem checking. Also forking the gems allows us to manually upgrade more concise, and more aware.

Guidelines for picking a gem

Our guidelines for picking a gem

  • Check if there is a gem around which does the same but with less code, but make sure you also keep in mind the user base, the size of the gem its dependencies.
  • Check if the gem is being actively developed.
  • Gems of active ruby communities have a preference.

Working with multi tenancy

We use acts_as_tenant for multi tenancy. We tend to include the tenant_id column on each of our tables to ensure that we can easily slice the data up if its ever needed. This may look like overhead but its really easy to query and index.

Frequently used gems in our projects

Some of the often used gems:

Usage of database migrations

Try to create as least possible migrations but be explicit, and endless list of migrations clutters the view. Feel free to modify existing migrations as long as they aren’t pushed to production or break existing functionality.

  • Keep migrations clean and easy to read.
  • Provide one migration file per table
  • Make sure you have your null checks in place.
  • Add indexes where necessary.
  • Make sure migrations are ALWAYS backwards compatible with your codebase. I.e the migrations are not allowed to break the codebase running on production. This allows for ZERO downtime deployment.

Security of our Rails projects

Security is important, we try to be as secure possible. We try to adhere to a bunch of best practices:

Dependencies / gem security

  • Bundler audit
  • We get notifications from GitHub’s automated vulnerabilities system

Test run CI security checks

  • Brakeman
  • Bundler-audit

SSL

  • Use rails config.enforce_ssl
  • Use lets encrypt for our our SSL certs

More reading