Skip to content

Aetherus/concern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Concern

Bring ActiveSupport::Concern to Elixir world.

Example

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

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:

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:

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

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, the package can be installed by adding concern to your list of dependencies in mix.exs:

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

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/concern.

About

Bring ActiveSupport::Concern to Elixir world

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages