0
votes

I'm writing docs with ex_doc and it seems very nice, but I have a problem. When a function has a map as a parameter, it is written as "map" inside documentation. I want to display it as "params".

Example

def login(conn, %{"email" => email, "password" => password}) do
  ...
end

...appears in documentation as:

login(conn, map)

I know I can write my function as:

def login(conn, %{"email" => email, "password" => password} = params) do
  ...
end

...to obtain:

login(conn, params)

...but this way I'll get an annoying warning saying that "params is unused", because I'm not using it inside my function.

Another option is to write my function as:

def login(conn, params)
def login(conn, %{"email" => email, "password" => password}) do
  ...
end

...but I don't want to write a useless line of code just to change the name of a parameter in documentation. Any ideas? Which one is the proper/best/cleanest way to accomplish this?

Update

As suggested, i tried to use spec to solve the problem.

  @spec login(conn :: %Plug.Conn{}, params :: map()) :: any()
  def login(conn, %{"email" => email, "password" => password}) do
  ...
  end

But this is what i'm getting in docs

login(conn, map)
login(
conn :: %Plug.Conn{
adapter: term(),
assigns: term(),
before_send: term(),
body_params: term(),
cookies: term(),
halted: term(),
host: term(),
method: term(),
owner: term(),
params: term(),
path_info: term(),
path_params: term(),
port: term(),
private: term(),
query_params: term(),
query_string: term(),
remote_ip: term(),
req_cookies: term(),
req_headers: term(),
request_path: term(),
resp_body: term(),
resp_cookies: term(),
resp_headers: term(),
scheme: term(),
script_name: term(),
secret_key_base: term(),
state: term(),
status: term()
},
params :: map()
) :: any()

map is still there instead of params, and i don't think that showing all params in conn struct will help reading docs

2

2 Answers

3
votes

If the argument name starts with _, it will be stripped from the documentation output and you won't get an unused variable warning. The following works for me:

def login(conn, %{"email" => email, "password" => password} = _params) do
  # ...
end

ex_doc output

2
votes

You should create typespecs for your functions:

@spec login(conn :: %Plug.Conn{}, params :: map()) :: any()
def login(conn, %{"email" => email, "password" => password}) do
  ...
end

Once the function has a @spec defined, the parameter names will be automatically taken from there.


Sidenote: although @specs are not mandatory, any mature Elixir/Erlang code is supposed to have them. The approach suggested above is correct, unlike doubling function clauses and/or assigning unused variables..