Skip to content
GenClient is an elixir library made to generate boilerplate code that I found myself repeatedly writing and changing when working with GenServers
Elixir
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
lib
test
.gitignore
LICENSE
README.md
mix.exs
mix.lock

README.md

GenClient

⚠ Don't use this in production ⚠

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.

Example

Here is a module written using a standard GenServer implementation

counter.ex
defmodule Counter do
  defdelegate increment(pid),       to: Client
  defdelegate increment_by(pid, x), to: Client
  defdelegate peek(pid),            to: Client
end
counter/client.ex
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
counter/server.ex
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
counter/impl.ex
defmodule Counter.Impl do
  def increment(state), do: state + 1
  def increment_by(state, x), do: state + x
end

The Previous Module Can be written using GenClient as follows:

counter.ex
defmodule Counter do
  use GenClient,
    for: Counter.Impl,
    calls: [:peek],
    casts: [:increment, :increment_by]
end
counter/counter.impl.ex
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
The resulting api will be exactly the same

Adding as a mix dependency

  def deps do
    [{:gen_client, git:"https://github.com/LukeWood/GenClient"}]
  end

or

def deps do
  [{:gen_client, "~> 1.0.1"}]
end
You can’t perform that action at this time.