Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-organize Markdown files #49

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 27 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,67 +17,56 @@ 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
```

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging those sections is a little out of the scope of this PR, but I think
it's acceptable.

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:

```shell
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].

<a href="https://www.alpine-lab.com">
<img src=".github/alpinelab-logo.png" width="40%" />
</a>

<a href="https://www.alpine-lab.com"><img src=".github/alpinelab-logo.png" width="40%" /></a>
<!-- Bibliography -->
[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
19 changes: 19 additions & 0 deletions docs/files.md
Original file line number Diff line number Diff line change
@@ -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`

<!-- Bibliography -->
[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
40 changes: 24 additions & 16 deletions docs/http-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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].

<!-- Bibliography -->
[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
25 changes: 17 additions & 8 deletions docs/rails.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -75,3 +81,6 @@ Rails.application.routes.draw do
end
end
```

<!-- Bibliography -->
[12-factor config]: https://12factor.net/config