Skip to main content
Table of contents

Applications

Conventions for Rails applications

The majority of GOV.UK applications are built using Ruby on Rails and over the years we have created a lot them. Along the way we’ve used a variety of patterns and conventions. We aim for GOV.UK apps to be consistent in their implementation with differences in domain logic. However, it isn’t practical to evolve all apps at the same pace so there can be differences in approaches used.

This document serves as a guide to the current conventions and preferences. It is intended to serve as a guide for teams creating new applications and for teams iterating older ones. If you are creating a new application do also consult the guides on setting up a new Rails application and how to name an application.

Non-Rails GOV.UK applications may still benefit from these conventions. Consider applying them if they do not conflict with existing conventions in an adopted framework.

Our approach

GOV.UK’s use of Rails is intended to be consistent with the conventions of the framework itself and we intend to embrace developments and deprecations from the framework. Where GOV.UK apps differ from Rails conventions (such as using the RSpec testing framework) these are intended to be consistent with common industry practices.

Tooling choices

Use GOV.UK supporting Gems

GOV.UK have published a number of gems that help achieve common needs across Ruby / Rails applications:

  • gds-api-adapters - provides common patterns to communicate between GOV.UK applications
  • gds-sso - integration with signon for user and application authentication
  • govuk_app_config - provides common configuration for applications such as logging, error handling and metric reporting
  • govuk_message_queue_consumer - provides a consistent means to work with the the RabbitMQ queue that the Publishing API broadcasts to
  • govuk_publishing_components - provides a framework for embedding common GOV.UK interface components and creating your own application specific ones
  • govuk_sidekiq - Provides common configuration for using sidekiq with GOV.UK infrastructure
  • govuk_schemas - Provides helper utilities for interfacing with govuk-content-schemas
  • govuk_test - Provides configuration and dependencies for headless browser testing
  • plek - Utility tool to access determine base URLs for GOV.UK applications for the current environment
  • rubocop-govuk - Provides GOV.UK linting rules for Ruby, Rails, RSpec and Rake
  • scss-lint-govuk - Provides linting for SCSS files according to GDS conventions
  • slimmer - Provides consistent templating for apps that serve content on the www.gov.uk host

Using these helps maintain consistency across the programme and enables common iterations to be pushed out. It is encouraged that gems are iterated or issues filed (example) when apps need to vary from conventions introduced by these gems.

Data storage

For non-specialist database needs you should use PostgreSQL with ActiveRecord. The db/seeds.rb can be used to populate the database for development and test environments.

For key-value datastore access (such as queues or distributed caches) Redis should be used. Typically a Redis datastore will not be shared between applications, for queue-based communication between applications we have precedent for using RabbitMQ via the Bunny gem.

For file storage local to an application Amazon S3 is the preferred choice, where this needs to be associated with a database ActiveStorage should be used.

Background job processing

The preferred approach for background job processing is to use ActiveJob with Sidekiq with the govuk_sidekiq gem providing configuration. ActiveJob is preferred due to it’s closer integration of Rails components (such as ActionMailer).

Scheduled background jobs for applications should also make use of Sidekiq, where sidekiq-scheduler is the conventional choice to achieve this.

JavaScript package management

For Rails applications you should use the Yarn package manager for JavaScript packages. Yarn is preferable to using NPM as Rails integrates directly with Yarn, providing default tasks and automating some workflows.

Frontend assets

GOV.UK applications use the Rails asset pipeline for building assets. We aspire to migrate to webpacker as the conventional approach when we have resolved blocking issues.

Sending emails

GOV.UK Notify is the preferred approach for sending email. The mail-notify gem is conventionally used to integrate Notify with ActionMailer. There is further documentation on how GOV.UK applications use Notify.

Testing utilities

The preferred framework for testing Rails applications is rspec-rails where we aim to adhere to the project’s conventions. rubocop-govuk provides a linting configuration for RSpec. For mocking and test doubles you should use the provided rspec-mocks framework.

When working with rspec-rails we prefer merging the spec_helper.rb and rails_helper.rb files into a single spec_helper.rb to avoid the complexities of two configuration files. We also choose to specify --require spec_helper in a .rspec file to avoid prefixing every test with require "spec_helper".

Common tools used with RSpec are:

The conventional testing framework for JavaScript files in GOV.UK Rails applications is jasmine. This is dictated by jasmine integrating with the asset-pipeline which rules out other common JavaScript testing frameworks such as Jest or Karma. Jasmine should be configured to run tests with Chrome headless as opposed to the default PhantomJS (which is a project no longer under development).

Configuration

Embrace 12 factor conventions

GOV.UK Rails applications aim to follow 12 factor conventions. These should manifest in your Rails application with practices such as:

  • environmental configuration done by environment variables, for example using ENV["DATABASE_URL"] over hardcoding the production database configuration;
  • close parity between development and production environments, for example using PostgreSQL in all environments - as opposed to SQLite for development and PostgreSQL for production;
  • avoiding, where possible, the need for additional configuration on the serving machine, for example needing additional Nginx rules to serve requests.

Inject secrets with environment variables

The conventional place to store secrets for a GOV.UK Rails application is config/secrets.yml. All production secrets should be populated with an environment variable; for dev and test environments it’s preferred to leave a usable dummy default if an actual secret isn’t needed (example).

We haven’t migrated to using the encrypted config/credentials.yml.enc introduced in Rails 5.2. This approach presents us with a few problems, most notably that we run our apps in Rails “production” environment in numerous places (integration, staging, production) and need different secrets for them.

Use api_only mode for API projects

For applications that do not serve requests to a web browser you should configure the Rails application to be API only, this simplifies Rails by removing unnecessary functionality. If you need to add a web browser interface to an API application you should consider creating a distinct frontend application (for example: email-alert-frontend and email-alert-api).

Editing of microcopy by non-developers

When it is intended for non-developers to edit microcopy in an application it is conventional to use Rails Internationalization (I18n) to abstract the copy outside of the application code. We use this even when an application is only in English. These files are stored in /config/locales as per Rails convention. You should only use these files for accessing copy and not for any application configuration.

Error handling

GOV.UK Rails applications should anticipate failure and do so gracefully. This happens automatically, to a degree, on GOV.UK frontend applications but not on admin applications where there is more granular control over error responses. GOV.UK Rails applications should be configured to provide GOV.UK branded error responses. Content Publisher provides an example of implementing this with the GOV.UK admin layout.

Organising your code

Organising code in a Rails application is frequently a source of debate and confusion, particularly as to what code belongs in the /app directory and what belongs in the /lib directory. We aim to follow what appears to be the prevalent convention where:

  • /app is used for:
    • the default Rails components (such as controllers, models, views, helpers, jobs)
    • commonly used classes in the application that have a common purpose and interface (good example: interactors, consistent interface and usage; bad example: reporters, just a one-off class)
  • /lib is used for:
    • classes that don’t logically fit into an app directory
    • complex business logic for the application, (for example, link expansion in the Publishing API)
    • Rake tasks

GOV.UK Rails applications should avoid creating an /app/lib directory, as this causes confusion with the prevalent /lib directory.

Configuration for applications, typically YAML files, should live in the /config directory.

Documenting your decisions

It’s conventional to create a /docs directory in GOV.UK Rails applications to store application documentation (which is typically linked to from the readme).

For recording the reasoning behind architectural decisions it’s conventional to use architectural decision records in the /docs/adr directory (example).

Testing strategies

We aim for well tested Rails applications that provide a good degree of coverage and provide assurances that an application is operating correctly. We value test suites that are fast to run, easy to read and test things consistently at different abstractions (unit, integration and functional).

Feature/system testing

When testing Rails applications from the perspective of an end user it is conventional to use RSpec Rails’ feature specs (new applications should use the more modern equivalent system specs) via govuk_test’s Capybara configuration.

GOV.UK have adopted the Future Learn readable feature test approach to writing feature tests in RSpec. This offers a similar level of readability of a cucumber test, without the difficulties in identifying the code used to perform the test.

Testing controllers

For testing controllers in Rails applications it is recommended to use request specs, which have been the recommended approach to replace controller specs reflecting the direction of Rails 5.

This page was last reviewed on 26 May 2020. It needs to be reviewed again on 26 May 2021 by the page owner #govuk-developers .
This page was set to be reviewed before 26 May 2021 by the page owner #govuk-developers. This might mean the content is out of date.