PragDave's component library is a much more feature complete library and is of much higher quality.
GenClient is an elixir metaprogramming library made to generate boilerplate code that I found myself repeatedly writing and changing when working with GenServers.
Every time I wanted to add or remove a parameter from a GenServer module I needed to do so in several places.
GenClient lets the programmer write their logic in a single location and keep it there.
Here is a module written using a standard GenServer implementation
defmodule Counter do
defdelegate increment(pid), to: Client
defdelegate increment_by(pid, x), to: Client
defdelegate peek(pid), to: Client
end
defmodule Counter.Client do
def increment(pid) do
GenServer.cast(pid, :increment)
end
def increment_by(pid, x) do
GenServer.cast(pid, {:increment_by, x})
end
def peek(pid) do
GenServer.call(pid, :peek)
end
end
defmodule Counter.Server do
def handle_cast(:increment, state) do
{:no_reply, Counter.Impl.increment(state)}
end
def handle_cast({:increment_by, x}, state) do
{:no_reply, Counter.Impl.increment_by(state, x)}
end
def handle_call(:peek, _from, state) do
{:reply, state, state}
end
end
defmodule Counter.Impl do
def increment(state), do: state + 1
def increment_by(state, x), do: state + x
end
defmodule Counter do
use GenClient,
for: Counter.Impl,
calls: [:peek],
casts: [:increment, :increment_by]
end
defmodule Counter.Impl do
# Casts
def increment(state), do: state + 1
def increment_by(state, amount), do: state + amount
# Calls
def peek(state) do
response = state
new_state = state
{response, new_state}
end
end
def deps do
[{:gen_client, git:"https://github.com/LukeWood/GenClient"}]
end
or
def deps do
[{:gen_client, "~> 1.0.1"}]
end