Skip to content

Commit

Permalink
Break up Rails conventions with headers
Browse files Browse the repository at this point in the history
Following feedback that this doc was somewhat hard to follow I've tried
to break this up into a number of sections to group together similar
concerns. The most notable change this causes to the doc is that the
testing tooling and testing strategy are in separate sections.
  • Loading branch information
kevindew committed Jun 8, 2020
1 parent 5ef55c0 commit 482d9f3
Showing 1 changed file with 104 additions and 98 deletions.
202 changes: 104 additions & 98 deletions source/manual/conventions-for-rails-applications.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,17 @@ conventions in an adopted framework.
[Ruby on Rails]: https://rubyonrails.org/
[consistent-govuk]: https://docs.google.com/document/d/1jEjPOFJ2s1cjQv9vHAbE-KF68LSletpnUVaG5lXlHy4/edit#heading=h.yod40rauhyhu

## Follow industry conventions
## 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.

GOV.UK Rails applications aim to follow
[12 factor](https://12factor.net/) conventions.
## Tooling choices

## Use GOV.UK supporting Gems
### Use GOV.UK supporting Gems

GOV.UK have published a number of gems that help achieve common needs across
Ruby / Rails applications:
Expand Down Expand Up @@ -90,7 +89,7 @@ introduced by these gems.
[slimmer]: https://github.com/alphagov/slimmer
[issue-example]: https://github.com/alphagov/govuk_app_config/issues/121

## Data storage
### Data storage

For non-specialist database needs you should use
[PostgreSQL](https://www.postgresql.org/) with [ActiveRecord][]. The
Expand All @@ -115,7 +114,7 @@ used.
[Amazon S3]: https://aws.amazon.com/s3/
[ActiveStorage]: https://guides.rubyonrails.org/active_storage_overview.html

## Background job processing
### Background job processing

The preferred approach for background job processing is to use [ActiveJob][]
with [Sidekiq][] with the [govuk_sidekiq][] gem providing configuration.
Expand All @@ -130,7 +129,7 @@ where [sidekiq-scheduler][] is the conventional choice to achieve this.
[ActionMailer]: https://guides.rubyonrails.org/action_mailer_basics.html
[sidekiq-scheduler]: https://github.com/moove-it/sidekiq-scheduler

## JavaScript package management
### JavaScript package management

For Rails applications you should use the [Yarn](https://yarnpkg.com) package
manager for JavaScript packages. Yarn is preferable to using
Expand All @@ -139,7 +138,7 @@ with Yarn, providing default tasks and automating some workflows.

[yarn-integration]: https://guides.rubyonrails.org/5_1_release_notes.html#yarn-support

## Frontend assets
### 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
Expand All @@ -149,7 +148,7 @@ resolved [blocking issues][].
[webpacker]: https://github.com/rails/webpacker
[blocking issues]: https://github.com/alphagov/govuk_publishing_components/issues/505

## Sending emails
### Sending emails

[GOV.UK Notify][] is the preferred approach for sending email. The
[mail-notify][] gem is conventionally used to integrate Notify with
Expand All @@ -160,12 +159,105 @@ GOV.UK applications use Notify.
[mail-notify]: https://github.com/dxw/mail-notify
[govuk-notify-docs]: /manual/govuk-notify.html

## Configure Rails as `api_only` for API projects
### Testing utilities

The preferred framework for testing Rails applications is [rspec-rails][] where
we aim to adhere to the projects 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`][rspec-file-example] in a [`.rspec` file][rspec-file]
to avoid prefixing every test with `require "spec_helper"`.

Common tools used with RSpec are:

- [webmock][] gem to stub HTTP requests, for stubbing communication between
GOV.UK applications [gds-api-adapters][] provides a library of helper methods
that are preferred to manual stubbing;
- [SimpleCov][] for monitoring code coverage;
- [factory_bot_rails][] for providing fixtures/test data;
- [Climate Control][] gem for modifying environment variables within tests;
- [`ActiveSupport::Testing::TimeHelpers`][time-helpers] for time manipulation.

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][jasmine-chrome] as opposed to the default PhantomJS
(which is a project no longer under development).

[rspec-rails]: https://relishapp.com/rspec/rspec-rails/docs
[rspec-mocks]: https://relishapp.com/rspec/rspec-mocks/docs
[spec_helper.rb]: https://github.com/rspec/rspec-core/blob/7b6b9c3f2e2878213f97d6fc9e9eb23c323cfe1c/lib/rspec/core/project_initializer/spec/spec_helper.rb
[rails_helper.rb]: https://github.com/rspec/rspec-rails/blob/a9e3f18c47cf83e0a40c3870f3bab5fe2f4e609a/lib/generators/rspec/install/templates/spec/rails_helper.rb
[single spec_helper.rb]: https://github.com/alphagov/content-publisher/blob/92eb7afe4344d32905b30204c94e033332342e6b/spec/spec_helper.rb
[rspec-file-example]: https://github.com/alphagov/content-publisher/blob/92eb7afe4344d32905b30204c94e033332342e6b/.rspec
[rspec-file]: https://github.com/rspec/rspec/wiki#rspec
[webmock]: https://github.com/bblimke/webmock
[webmock-localhost]: https://github.com/alphagov/content-publisher/blob/8c88972d461c8c25ae4e8c8b22c367eb28d6b79a/spec/spec_helper.rb#L18
[simplecov]: https://github.com/colszowka/simplecov
[factory_bot_rails]: https://github.com/thoughtbot/factory_bot_rails
[factory-bot-lint]: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#linting-factories
[Climate Control]: https://github.com/thoughtbot/climate_control
[time-helpers]: https://api.rubyonrails.org/v6.0.2/classes/ActiveSupport/Testing/TimeHelpers.html
[jasmine]: https://github.com/jasmine/jasmine-gem
[asset-pipeline]: #frontend-assets
[jasmine-chrome]: https://github.com/alphagov/content-publisher/blob/f26d9b551842fdf2084159b5b7f1bb078da56936/spec/javascripts/support/jasmine_helper.rb
## Configuration

### Embrace 12 factor conventions

GOV.UK Rails applications aim to follow
[12 factor](https://12factor.net/) 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.

### 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][].
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][]).

[API only]: https://guides.rubyonrails.org/api_app.html
[email-alert-frontend]: https://github.com/alphagov/email-alert-frontend
[email-alert-api]: https://github.com/alphagov/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)][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.

[i18n]: https://guides.rubyonrails.org/i18n.html

### Error handling

GOV.UK Rails applications should anticipate failure and do so gracefully. This
[happens automatically, to a degree, on GOV.UK frontend
applications][frontend-errors] 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][cp-errors] provides an example of implementing this with
the [GOV.UK admin layout][].

[frontend-errors]: /manual/errors.html
[cp-errors]: https://github.com/alphagov/content-publisher/pull/1252
[GOV.UK admin layout]: https://components.publishing.service.gov.uk/component-guide/layout_for_admin

## Organising your code

Expand Down Expand Up @@ -209,72 +301,14 @@ to use [architectural decision records][adr] in the `/docs/adr` directory
[adr]: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
[adr-example]: https://github.com/alphagov/content-publisher/blob/master/docs/adr/0002-use-local-datastore.md

## 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)][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.

[i18n]: https://guides.rubyonrails.org/i18n.html

## Error handling

GOV.UK Rails applications should anticipate failure and do so gracefully. This
[happens automatically, to a degree, on GOV.UK frontend
applications][frontend-errors] 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][cp-errors] provides an example of implementing this with
the [GOV.UK admin layout][].

[frontend-errors]: /manual/errors.html
[cp-errors]: https://github.com/alphagov/content-publisher/pull/1252
[GOV.UK admin layout]: https://components.publishing.service.gov.uk/component-guide/layout_for_admin

## 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)][cp-testing-strategy].

### Common tooling

The preferred framework for testing Rails applications is [rspec-rails][] where
we aim to adhere to the projects 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.
- Specifying [`--require spec_helper`][rspec-file-example] in a
[`.rspec` file][rspec-file] to avoid prefixing every test with
`require "spec_helper"`.

The conventional choice for stubbing HTTP requests is the [webmock][] gem,
which should be configured webmock to disable [real requests outside of
localhost][webmock-localhost]. For stubbing communication between GOV.UK
applications [gds-api-adapters][] provides a library of helper methods that
are preferred to manual stubbing.

For monitoring code coverage we typically use the [SimpleCov] gem.

For fixtures we conventionally use [factory_bot_rails][] and it is recommended
that you [lint your factories][factory-bot-lint] as part of an applications
CI process.

When utilising environment variables in tests it is recommended to use
the [Climate Control][] gem which offers a simple consistent approach.

For time manipulation in tests Rails has built in helpers in
[`ActiveSupport::Testing::TimeHelpers`][time-helpers], it is preferable to use
these rather than an install an additional gem such as Timecop.
[cp-testing-strategy]: https://github.com/alphagov/content-publisher/blob/f26d9b551842fdf2084159b5b7f1bb078da56936/docs/testing-strategy.md

### Feature/system testing

Expand Down Expand Up @@ -304,31 +338,3 @@ approach][rspec-request-moj] to replace [controller specs][] reflecting the
[rspec-request-moj]: https://medium.com/just-tech/rspec-controller-or-request-specs-d93ef563ef11
[controller specs]: https://relishapp.com/rspec/rspec-rails/docs/controller-specs
[controller-rails-5]: https://github.com/rails/rails/issues/18950

### Javascript

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][jasmine-chrome] as opposed to the default PhantomJS
(which is a project no longer under development).

[cp-testing-strategy]: https://github.com/alphagov/content-publisher/blob/f26d9b551842fdf2084159b5b7f1bb078da56936/docs/testing-strategy.md
[rspec-rails]: https://relishapp.com/rspec/rspec-rails/docs
[rspec-mocks]: https://relishapp.com/rspec/rspec-mocks/docs
[spec_helper.rb]: https://github.com/rspec/rspec-core/blob/7b6b9c3f2e2878213f97d6fc9e9eb23c323cfe1c/lib/rspec/core/project_initializer/spec/spec_helper.rb
[rails_helper.rb]: https://github.com/rspec/rspec-rails/blob/a9e3f18c47cf83e0a40c3870f3bab5fe2f4e609a/lib/generators/rspec/install/templates/spec/rails_helper.rb
[single spec_helper.rb]: https://github.com/alphagov/content-publisher/blob/92eb7afe4344d32905b30204c94e033332342e6b/spec/spec_helper.rb
[rspec-file-example]: https://github.com/alphagov/content-publisher/blob/92eb7afe4344d32905b30204c94e033332342e6b/.rspec
[rspec-file]: https://github.com/rspec/rspec/wiki#rspec
[webmock]: https://github.com/bblimke/webmock
[webmock-localhost]: https://github.com/alphagov/content-publisher/blob/8c88972d461c8c25ae4e8c8b22c367eb28d6b79a/spec/spec_helper.rb#L18
[simplecov]: https://github.com/colszowka/simplecov
[factory_bot_rails]: https://github.com/thoughtbot/factory_bot_rails
[factory-bot-lint]: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#linting-factories
[Climate Control]: https://github.com/thoughtbot/climate_control
[time-helpers]: https://api.rubyonrails.org/v6.0.2/classes/ActiveSupport/Testing/TimeHelpers.html
[jasmine]: https://github.com/jasmine/jasmine-gem
[asset-pipeline]: #frontend-assets
[jasmine-chrome]: https://github.com/alphagov/content-publisher/blob/f26d9b551842fdf2084159b5b7f1bb078da56936/spec/javascripts/support/jasmine_helper.rb

0 comments on commit 482d9f3

Please sign in to comment.