# 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-ce/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 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])
```

[Entity]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/entities.rb
[validation, and coercion of the parameters]: https://github.com/ruby-grape/grape#parameter-validation-and-coercion