debian-mirror-gitlab/doc/development/api_styleguide.md
2020-04-08 14:13:33 +05:30

129 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API styleguide
This styleguide recommends best practices for API development.
## Instance variables
Please do not use instance variables, there is no need for them (we don't need
to access them as we do in Rails views), local variables are fine.
## Entities
Always use an [Entity] to present the endpoint's payload.
## Methods and parameters description
Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
(see <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb>
for a good example):
- `desc` for the method summary. You should pass it a block for additional
details such as:
- The GitLab version when the endpoint was added. If it is behind a feature flag, mention that instead: _This feature is gated by the :feature\_flag\_symbol feature flag._
- If the endpoint is deprecated, and if so, when will it be removed
- `params` for the method params. This acts as description,
[validation, and coercion of the parameters]
A good example is as follows:
```ruby
desc 'Get all broadcast messages' do
detail 'This feature was introduced in GitLab 8.12.'
success Entities::BroadcastMessage
end
params do
optional :page, type: Integer, desc: 'Current page number'
optional :per_page, type: Integer, desc: 'Number of messages per page'
end
get do
messages = BroadcastMessage.all
present paginate(messages), with: Entities::BroadcastMessage
end
```
## Declared params
> Grape allows you to access only the parameters that have been declared by your
`params` block. It filters out the params that have been passed, but are not
allowed.
<https://github.com/ruby-grape/grape#declared>
### Exclude params from parent namespaces
> By default `declared(params)`includes parameters that were defined in all
parent namespaces.
<https://github.com/ruby-grape/grape#include-parent-namespaces>
In most cases you will want to exclude params from the parent namespaces:
```ruby
declared(params, include_parent_namespaces: false)
```
### When to use `declared(params)`
You should always use `declared(params)` when you pass the params hash as
arguments to a method call.
For instance:
```ruby
# bad
User.create(params) # imagine the user submitted `admin=1`... :)
# good
User.create(declared(params, include_parent_namespaces: false).to_h)
```
>**Note:**
`declared(params)` return a `Hashie::Mash` object, on which you will have to
call `.to_h`.
But we can use `params[key]` directly when we access single elements.
For instance:
```ruby
# good
Model.create(foo: params[:foo])
```
## Using HTTP status helpers
For non-200 HTTP responses, use the provided helpers in `lib/api/helpers.rb` to ensure correct behaviour (`not_found!`, `no_content!` etc.). These will `throw` inside Grape and abort the execution of your endpoint.
For `DELETE` requests, you should also generally use the `destroy_conditionally!` helper which by default returns a `204 No Content` response on success, or a `412 Precondition Failed` response if the given `If-Unmodified-Since` header is out of range. This helper calls `#destroy` on the passed resource, but you can also implement a custom deletion method by passing a block.
## Using API path helpers in GitLab Rails codebase
Because we support [installing GitLab under a relative URL], one must take this
into account when using API path helpers generated by Grape. Any such API path
helper usage must be in wrapped into the `expose_path` helper call.
For instance:
```haml
- endpoint = expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid))
```
## Internal API
The [internal API](./internal_api.md) is documented for internal use. Please keep it up to date so we know what endpoints
different components are making use of.
[Entity]: https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/entities.rb
[validation, and coercion of the parameters]: https://github.com/ruby-grape/grape#parameter-validation-and-coercion
[installing GitLab under a relative URL]: https://docs.gitlab.com/ee/install/relative_url.html
## Testing
When writing tests for new API endpoints, consider using a schema [fixture](./testing_guide/best_practices.md#fixtures) located in `/spec/fixtures/api/schemas`. You can `expect` a response to match a given schema:
```ruby
expect(response).to match_response_schema('merge_requests')
```