Packages

`Behave` checks whether a module implements the behaviour defined in another module.

Current section

Files

Jump to
behave lib behave.ex
Raw

lib/behave.ex

defmodule Behave do
@moduledoc """
`Behave` allows you to check whether one Elixir module implements a
given
[Behaviour](https://elixir-lang.org/getting-started/typespecs-and-behaviours.html).
"""
@doc """
Determines whether a given `implementation_module` is both a module and
implements the behaviour required by `behaviour_module`.
Unfortunately, Elixir doesn't have an `is_module` guard, and you have to use
`is_atom`, as Modules are considered atoms.
```
iex> is_atom(SomeModule)
true
```
Elixir will show you at compile-time (via a warning) if you haven't
implemented a required function in a Behaviour. However, there is no way to
determine whether or not a given Module implements another Module's
Behaviour.
## Return values
| **Value** | **Meaning** |
| :ok | `module` meets the criteria for the `behaviour_module` |
| {:error, :not_a_module, module} | `module` is not actually a Module |
| {:error, :behaviour_not_implemented} | `module` does not implement `behaviour_module` |
"""
@spec behaviour_implemented?(implementation_module :: module, behaviour_module :: module) ::
:ok | {:error, :not_a_module, value :: term} | {:error, :behaviour_not_implemented}
def behaviour_implemented?(implementation_module, behaviour_module) do
cond do
not is_module?(implementation_module) ->
{:error, :not_a_module, implementation_module}
not is_module?(behaviour_module) ->
{:error, :not_a_module, behaviour_module}
true ->
implements_behaviour?(implementation_module, behaviour_module)
end
end
defp is_module?(module) when is_atom(module) do
case Code.ensure_loaded(module) do
{:module, ^module} ->
true
_ ->
false
end
end
defp is_module?(_), do: false
defp implements_behaviour?(implementation_module, behaviour_module) do
implements_behaviour =
:attributes
|> implementation_module.module_info()
|> Keyword.get(:behaviour, [])
|> Enum.member?(behaviour_module)
if implements_behaviour do
:ok
else
{:error, :behaviour_not_implemented}
end
end
end