Our Ruby on Rails conventions
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 testsbundler-audit
on every build to check for reported vulnerabilitiesbrakeman
to check for obvious code leakssimplecov
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:
- ged/ruby-pg: A PostgreSQL client library for Ruby
- rbenv/rbenv: Groom your app’s Ruby environment
- Slim - A Fast, Lightweight Template Engine for Ruby
- Sass: Syntactically Awesome Style Sheets
- seattlerb/minitest: minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking.
- heartcombo/simple_form: Forms made easy for Rails! It's tied to a simple DSL, with no opinion on markup.
- carrierwaveuploader/carrierwave: Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks
- rails/spring: Rails application preloader
- Active Admin: The administration framework for Ruby on Rails
- deivid-rodriguez/byebug: Debugging in Ruby 2
- teamcapybara/capybara: Acceptance test framework for web applications
- BetterErrors/better_errors: Better error page for Rack apps
- Guard - For automatic running of tests, migrations and livereload
- Omniauth - For authenticating against OAuth
- GraphQL - For building GraphQL APIs
- neat - for responsive css
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