Packages

Provides simple tools to implement the "Observer" pattern.

Current section

Files

Jump to
observable lib observable.ex
Raw

lib/observable.ex

defmodule Observable do
@callback handle_notify({atom, any}) :: any
def observer do
quote do
@behaviour Observable
def handle_notify(_notification) do
:ok
end
defoverridable Observable
end
end
def notifier do
quote do
import Observable, only: [observations: 1]
Module.register_attribute(__MODULE__, :observations, accumulate: true)
end
end
def notify([struct | _] = data, action) when is_map(struct) do
module = struct.__struct__
notify(module, action, data)
end
def notify(struct, action) when is_map(struct) do
module = struct.__struct__
notify(module, action, struct)
end
def notify(module, action, data) do
for observer <- module.__observations__(action) do
apply(observer, :handle_notify, [{action, data}])
end
end
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
defmacro observations(do: block) do
quote do
@before_compile Observable
try do
import Observable
unquote(block)
after
:ok
end
end
end
defmacro on_action(action, observer) do
quote do
Module.put_attribute(__MODULE__, :observations, {unquote(action), unquote(observer)})
end
end
defmacro __before_compile__(_env) do
quote do
def __observations__ do
@observations
end
def __observations__(action_to_find) do
Enum.reduce(@observations, [], fn {action, observer}, observers ->
if action_to_find == action, do: [observer | observers], else: observers
end)
end
end
end
end