Packages

Automatically creates a behaviour from a module's specs.

Current section

5 Versions

Jump to

Compare versions

4 files changed
+17 additions
-35 deletions
  @@ -7,12 +7,15 @@ Turns a module's specs into callbacks.
7 7
8 8 Lets you state that a module behaves like another, without writing behaviour callbacks.
9 9
10 + Uses a macro for 1.7, until https://github.com/elixir-lang/elixir/issues/8085 is fixed.
11 +
10 12 For example:
11 13 ```elixir
12 14 defmodule API do
13 15 use BehavesLike
16 + import BehavesLike, only: [spec_and_callback: 1]
14 17
15 - @spec get(binary()) :: {:ok, any()} | {:error, any()}
18 + spec_and_callback get(binary()) :: {:ok, any()} | {:error, any()}
16 19 def get(id) do
17 20 Backend.get(id)
18 21 end
  @@ -28,8 +31,6 @@ defmodule Backend do
28 31 end
29 32 ```
30 33
31 - Please note, this library uses undocumented private calls to manipulate the elixir compiler's ets tables. Use at your own risk.
32 -
33 34 ## Installation
34 35
35 36 From Hex:
  @@ -37,11 +38,11 @@ From Hex:
37 38 ```elixir
38 39 def deps do
39 40 [
40 - {:behaves_like, "~> 0.3.0"}
41 + {:behaves_like, "~> 0.4.0"}
41 42 ]
42 43 end
43 44 ```
44 45
45 46 ## Usage
46 47
47 - Just add `use BehavesLike` to your module, then you can use the standard `@behaviour` attribute in other modules to refer to it.
48 + Import the required macro, then declare your specs with `spec_and_callback/1`, as in the example above.
  @@ -1,14 +1,13 @@
1 1 {<<"app">>,<<"behaves_like">>}.
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,
4 - <<"Automatically creates a behaviour from a module's specs. This lib uses undocumented calls, please don't use it. :)">>}.
5 - {<<"elixir">>,<<"~> 1.7.1">>}.
4 + <<"Automatically creates a behaviour from a module's specs.">>}.
5 + {<<"elixir">>,<<"~> 1.6">>}.
6 6 {<<"files">>,
7 7 [<<"lib">>,<<"lib/behaves_like.ex">>,<<".formatter.exs">>,<<"mix.exs">>,
8 8 <<"README.md">>,<<"LICENSE">>]}.
9 9 {<<"licenses">>,[<<"MIT">>]}.
10 10 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/koudelka/behaves_like">>}]}.
11 - {<<"maintainers">>,[<<"Michael Shapiro">>]}.
12 11 {<<"name">>,<<"behaves_like">>}.
13 12 {<<"requirements">>,[]}.
14 - {<<"version">>,<<"0.3.0">>}.
13 + {<<"version">>,<<"0.4.0">>}.
  @@ -7,9 +7,9 @@ defmodule BehavesLike do
7 7 For example:
8 8 ```elixir
9 9 defmodule API do
10 - use BehavesLike
10 + import BehavesLike, only: [spec_and_callback: 1]
11 11
12 - @spec get(binary()) :: {:ok, any()} | {:error, any()}
12 + spec_and_callback get(binary()) :: {:ok, any()} | {:error, any()}
13 13 def get(id) do
14 14 Backend.get(id)
15 15 end
  @@ -26,28 +26,10 @@ defmodule BehavesLike do
26 26 ```
27 27 """
28 28
29 - defmacro __using__(_opts) do
29 + defmacro spec_and_callback(spec) do
30 30 quote do
31 - @before_compile unquote(__MODULE__)
31 + @spec unquote(spec)
32 + @callback unquote(spec)
32 33 end
33 34 end
34 -
35 - defmacro __before_compile__(_env) do
36 - quote do
37 - {_set, bag} = :elixir_module.data_tables(__MODULE__)
38 - unquote(__MODULE__).get_typespecs(bag, :spec)
39 - |> Enum.each(&unquote(__MODULE__).store_typespec(bag, :callback, &1))
40 - end
41 - end
42 -
43 - @doc false
44 - def get_typespecs(bag, type) do
45 - :ets.lookup_element(bag, type, 2)
46 - end
47 -
48 - @doc false
49 - def store_typespec(bag, key, value) do
50 - :ets.insert(bag, {key, value})
51 - :ok
52 - end
53 35 end
  @@ -1,17 +1,17 @@
1 1 defmodule BehavesLike.MixProject do
2 2 use Mix.Project
3 3
4 - @version "0.3.0"
4 + @version "0.4.0"
5 5
6 6 def project do
7 7 [
8 8 app: :behaves_like,
9 9 version: @version,
10 - elixir: "~> 1.7.1",
10 + elixir: "~> 1.6",
11 11 start_permanent: Mix.env() == :prod,
12 12 deps: deps(),
13 13 dialyzer: dialyzer(),
14 - description: "Automatically creates a behaviour from a module's specs. This lib uses undocumented calls, please don't use it. :)",
14 + description: "Automatically creates a behaviour from a module's specs.",
15 15 package: package(),
16 16 docs: docs(),
17 17 ]