UnifiApi.Resource (UnifiApi v0.4.0)

Copy Markdown View Source

Shared plumbing for the endpoint modules.

Every resource module under UnifiApi.Network.* and UnifiApi.Protect.* needs the same three things: the path prefix for its API surface, id validation before interpolation, and optional-query-param assembly. Before v0.4.0 that was 37 copies of defp prefix, 20 copies of defp maybe_param, and 115 inline Client.validate_id!/1 calls — so a missing validate_id! in any one module was invisible, and moving the prefixes off global Application env would have meant 37 near-identical edits.

Usage

defmodule UnifiApi.Network.Devices do
  use UnifiApi.Resource, api: :network

  def get(client, site_id, device_id) do
    Client.get(client, "#{prefix(client)}/v1/sites/#{id!(site_id)}/devices/#{id!(device_id)}")
  end
end

api: is one of UnifiApi.Client.api/0:network, :protect, :network_v1, :protect_v1.

What it injects

  • alias UnifiApi.Client
  • prefix(client) — this module's path prefix, read from the client (not from Application env; see UnifiApi.Client.prefix/2).
  • id!(id)UnifiApi.Client.validate_id!/1, shortened because it appears inline in interpolations where a long name hurts readability.
  • maybe_param(params, key, value) — prepends {key, value} unless value is nil.
  • maybe_csv(params, key, values) — prepends a comma-joined {key, csv} unless values is nil or empty.

All four are private to the using module. The macro also defines __resource__/1 for introspection: __resource__(:api) returns the API surface and __resource__(:helpers) returns captures of the injected helpers, which is also what keeps an unused one from tripping --warnings-as-errors.