We use Apple macbooks. Preferably 13”’ macbook pro’s or airs because for portibility purposes. To install your laptop. Please checkout the chapter on new laptop setup.
Ruby / Rails version management
Versions are managed by rbenv. We use 2.6.5 of Ruby at the moment.
Authentication & authorization
We use cancancan for authorization. Devise for authentication. Sometimes with register flows, sometimes wihtout out and only Gmail flows etc.
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 datamodel 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 focussing on the front-end.
This allows us to:
- Deliver the back-end quickly and iteratively (usually on day one)
- Give the client the opportunity to already get familiar with the datamodel
- Check if we have any fields missed
Use rebuild rake tasks
We use a couple of rake tasks prefixed with rebuild to:
- Build after a clone
- Rebuild the database for guard
- Get remote production data local and rebuild and test against the current codebase
- To get a presentable state
rebuild:for_demowhich can be demo’ed
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:
Make sure concerns don’t leak. I.e. a concern should be standalone, reusable and strive for not needing extra methods on the model implemting 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.
We use continous integration for our test suite. Every push/pull-request is being checked against our test suite.
rake testto check for tests
bundler-auditon every build to check for reported vulnerabilities
brakemanto check for obvious code leaks
simplecovfor 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 prematurly 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 parttern 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 isnt 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 userbase, 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, and endless list of migrations clutters the view. Feel free to modify existing migrations as long as they arent 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 ssecurity checks
- Use rails
- Use lets encrypt for our our SSL certs