README.md

# Concern

Bring `ActiveSupport::Concern` to Elixir world.

## Example

```elixir
defmodule MyConcern do
  use Concern   

  using do
    quote do
      def who_am_i, do: __MODULE__
    end
  end

  before_compile do
    quote do
      IO.inspect(__MODULE__)
    end
  end
end

defmodule MyModule do
  use MyConcern
end

MyModule.who_am_i  #=> MyModule
```

## The problem concern tries to solve
  
The problem with mixin style modules is that, suppose you have the following modules 

```elixir
defmodule MixinA do
  defmacro __using__(_) do
    quote do
      def foo, do: __MODULE__
    end
  end
end

defmodule MixinB do
  use MixinA  

  defmacro __using__(_) do
    quote do
      def bar, do: foo
    end
  end
end

defmodule MyModule do
  use MixinB
end

MyModule.bar
```

You expect the return value be `MyModule`, but instead it gives you a `CompileError`.
That's because `foo` is injected into `MixinB`, not `MyModule`.

Maybe you'll try to call `MixinB.foo` in `bar`:

```elixir
defmodule MixinA do
  defmacro __using__(_) do
    quote do
      def foo, do: __MODULE__
    end
  end
end

defmodule MixinB do
  use MixinA  

  defmacro __using__(_) do
    quote do
      def bar, do: MixinB.foo  #<----- Note this line
    end
  end
end

defmodule MyModule do
  use MixinB
end

MyModule.bar  #=> MixinB
```

This is not you want.

Or you may try this:

```elixir
defmodule MixinA do
  defmacro __using__(_) do
    quote do
      def foo, do: __MODULE__
    end
  end
end

defmodule MixinB do
  defmacro __using__(_) do
    quote do
      def bar, do: foo
    end
  end
end

defmodule MyModule do
  use MixinA
  use MixinB
end

MyModule.bar  #=> MyModule
```

But why should `MyModule` know the existence of `MixinA` when `MyModule` directly uses nothing in `MixinA`?

With `Concern`, you can do this

```elixir
defmodule MixinA do
  use Concern

  using do
    quote do
      def foo, do: __MODULE__
    end
  end
end

defmodule MixinB do
  use Concern
  use MixinA  

  using do
    quote do
      def bar, do: foo
    end
  end
end

defmodule MyModule do
  use MixinB
end

MyModule.bar  #=> MyModule
```

## Caveat

* `using` is not parameterized.
* Can't access env in `before_compile` block.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `concern` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:concern, "~> 0.1.0"}
  ]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/concern](https://hexdocs.pm/concern).