diff --git a/README.md b/README.md
index 5255e97..c072a00 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,11 @@ Code style used by AlpineLab in all our projects.
## Usage
-1. Add `rubocop` gems to your `Gemfile` (or `gems.rb`, or `gems.deps.rb`):
+1. Add those gems to your `Gemfile` (or `gems.rb`, or `gems.deps.rb`):
```ruby
group :development, :test do
+ gem "alpinelab-codestyle", "~> x.y", require: false
gem "rubocop", "~> x.y", require: false
gem "rubocop-md", "~> x.y", require: false
end
@@ -16,53 +17,33 @@ Code style used by AlpineLab in all our projects.
or install them manually:
```shell
- gem install rubocop rubocop-md
+ gem install alpinelab-codestyle rubocop rubocop-md
```
-2. Add `alpinelab-codestyle` gem to your `Gemfile`
-(or `gems.rb`, or `gems.deps.rb`):
-
- ```ruby
- group :development, :test do
- gem "alpinelab-codestyle", "~> x.y"
- end
- ```
-
- or install it manually:
-
- ```shell
- gem install alpinelab-codestyle
- ```
-
-3. Create or prepend your Rubocop configuration (usually `.rubocop.yml`) with:
+2. Create or prepend your Rubocop configuration (usually `.rubocop.yml`) with:
```yaml
inherit_gem:
alpinelab-codestyle:
- config/default.yml
- - config/rails.yml
+ - config/rails.yml # for Rails projects only
```
## Best practices
-Some conventions are adopted and enforced, in no particular order:
-
-1. Developer-specific configuration files must be git-ignored globally, _e.g._:
+Some conventions are adopted and enforced, but cannot be translated as Rubocop
+rules (or are not supposed to). You will find those conventions as Markdown
+files in the [`docs`](docs/) directory of this project, organized by subject:
- * `.ruby-{version,gemset}`
- * `docker-compose.override.yml`
-
-2. Project-specific configuration files must be git-ignored per project, _e.g._:
-
- * `config/database.yml`
+* [File structure and organisation](docs/files.md)
+* [Rails-specific conventions](docs/rails.md)
+* [HTTP API development guidelines](docs/http-api.md)
## Releases
To release this very gem:
-1. Bump its version number in
-[`lib/alpine_lab/code_style/version.rb`](lib/alpine_lab/code_style/version.rb)
-according to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html)
+1. Bump its version number in [`version.rb`] respecting [Semantic Versioning 2]
2. Use Bundler Rake task to build, tag and push the gem:
@@ -70,13 +51,22 @@ according to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html)
rake release
```
- _(with Docker, you need to have configured both
- [Git authentication](https://github.com/alpinelab/docker-ruby-dev/blob/latest/RECIPES.md#git-authentication)
- and [Rubygems authentication](https://github.com/alpinelab/docker-ruby-dev/blob/latest/RECIPES.md#rubygems-authentication)
- then you can run the same command with `docker-compose run app rake release`)_
+ _(using Docker, both [Git authentication] and [Rubygems authentication] must
+ be configured to run `docker-compose run app rake release`)_
## License
-This project is developed by [Alpine Lab](https://www.alpine-lab.com) and released under the terms of the [MIT license](LICENSE.md).
+This project is developed by [Alpine Lab] and released under the terms of the
+[MIT license].
+
+
+
+
-
+
+[Alpine Lab]: https://www.alpine-lab.com
+[git authentication]: https://github.com/alpinelab/docker-ruby-dev/blob/latest/RECIPES.md#git-authentication
+[MIT license]: LICENSE.md
+[RubyGems authentication]: https://github.com/alpinelab/docker-ruby-dev/blob/latest/RECIPES.md#rubygems-authentication
+[Semantic Versioning 2]: https://semver.org/spec/v2.0.0.html
+[`version.rb`]: lib/alpine_lab/code_style/version.rb
diff --git a/docs/files.md b/docs/files.md
new file mode 100644
index 0000000..178ae7b
--- /dev/null
+++ b/docs/files.md
@@ -0,0 +1,19 @@
+# File structure and organization
+
+## Git-ignore'd files
+
+**Developer-specific** configuration files must be
+[git-ignored globally], _e.g._:
+
+* `.ruby-version`
+* `.ruby-gemset`
+* `docker-compose.override.yml`
+
+**Project-specific** configuration files must be
+[git-ignored locally] (_i.e._ per project), _e.g._:
+
+* `config/database.yml`
+
+
+[git-ignored locally]: https://help.github.com/articles/ignoring-files/#create-a-local-gitignore
+[git-ignored globally]: https://help.github.com/articles/ignoring-files/#create-a-global-gitignore
diff --git a/docs/http-api.md b/docs/http-api.md
index a2e2272..17de555 100644
--- a/docs/http-api.md
+++ b/docs/http-api.md
@@ -2,22 +2,20 @@
## API description
-We use [OpenAPI Specification 2.0](https://swagger.io/specification/v2/)
-to describe our API.
+We use [OpenAPI Specification 2.0] to describe our API.
This OAS 2.0 description is then used by:
-* [Dredd](https://github.com/apiaryio/dredd) to check our implementation
-* [Committee](https://github.com/interagent/committee) to validate input data
-* [SwaggerUI](https://swagger.io/tools/swagger-ui) to generate documentation
+* [Dredd] to check our implementation
+* [Committee] to validate input data
+* [SwaggerUI] to generate documentation
## JSON generation
-We use [jBuilder](https://github.com/rails/jbuilder) to write our JSON views.
+We use [jBuilder] to write our JSON views.
-We may use [Oj](https://github.com/ohler55/oj) to parse and marshall
-JSON on performance-demanding projects (`jBuilder` uses
-[MultiJSON](https://github.com/intridea/multi_json) that uses `Oj` as soon as
-it is required, so we simply have to add it to the project `Gemfile`).
+We may use [Oj] to parse and marshall JSON on performance-demanding projects
+([jBuilder] uses [MultiJSON] that uses [Oj] as soon as it is required,
+so we simply have to add it to the project `Gemfile`).
## Controllers segregation
@@ -28,9 +26,19 @@ Instead, we favour an approach where API controllers are namespaced in a module
named `API` (_e.g._ `ResourcesController` processes HTML requests while
`API::ResourcesController` processes JSON requests).
-It avoids unreadable controller actions with many `respond_to` and `format`,
-but is a bit less [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
-because we basically need 2 controllers per resource.
-This should incentivise us to keep business logic separated in external modules
-like service classes, thus enforcing the
-[SRP](https://en.wikipedia.org/wiki/Single_responsibility_principle).
+It avoids unreadable controller actions with many calls to `respond_to` and
+`format`, but is a bit less [Don't Repeat Yourself] because we basically need
+two controllers per resource. On the other hand, it incentivises us to keep
+business logic separated in external modules like service classes,
+thus enforcing the [Single Responsibility Principle].
+
+
+[Committee]: https://github.com/interagent/committee
+[Don't Repeat Yourself]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
+[Dredd]: https://github.com/apiaryio/dredd
+[jBuilder]: https://github.com/rails/jbuilder
+[MultiJSON][https://github.com/intridea/multi_json]
+[Oj]: https://github.com/ohler55/oj
+[OpenAPI Specification 2.0]: https://swagger.io/specification/v2/
+[Single Responsibility Principle]: https://en.wikipedia.org/wiki/Single_responsibility_principle
+[SwaggeUI]: https://swagger.io/tools/swagger-ui
diff --git a/docs/rails.md b/docs/rails.md
index c494225..6d8d350 100644
--- a/docs/rails.md
+++ b/docs/rails.md
@@ -1,19 +1,25 @@
-# Rails conventions
+# Rails-specific conventions
-## App behavior should be configured via environment variables
+## Application configuration
-When implementing new features, it should not depend on current
-`RAILS_ENV` value, but environment variable(s) specific to the
-feature.
+Application configuration should **depend on environment variables**,
+and absolutely **not rely on `RAILS_ENV`** value (nor `Rails.env`),
+respecting the [12-factor app methodology][12-factor config].
-* Avoid modifying `config/environments/*.rb`, and keep default
- Rails configuration (this will also help when updating Rails)
-* Avoid testing:
+Specifically, the following rules should be followed:
+
+* Avoid modifying `config/environments/*.rb`: keep default Rails configuration
+ in there untouched (this will also make Rails upgrades a lot smoother)
+* Write application configuration in `config/application.rb`
+* Avoid testing any of:
+ * `ENV["RACK_ENV"]`
+ * `ENV["RAILS_ENV"]`
* `Rails.env.development?`
* `Rails.env.production?`
* `Rails.env.test?`
Examples:
+
``` ruby
# bad:
module MyRailsApp
@@ -75,3 +81,6 @@ Rails.application.routes.draw do
end
end
```
+
+
+[12-factor config]: https://12factor.net/config