README.md

# Fastfwd

Plugin style function forwarding in Elixir, for adapters, factories and other fun.
Fastfwd can be used to provide functionality similar to Rails' ActiveRecord type column,
or to allow third party libraries or applications to extend the functionality of your code.

## Installation

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

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

## Example

Fastfwd proves an alternative to hardcoding which module should be used for each type of data, for example with a case statement, like this

```elixir
    case bread_type do
      :barm -> Bread.Barm.bake(loaves_quantity)
      :stottie -> Bread.Stottie.bake(loaves_quantity)
      :sliced -> Bread.SlicedWhiteLoaf.bake(loaves_quantity)
      :sourdough -> Bread.Sourdough.bake(loaves_quantity)
    end
```

Fastfwd will find all suitable modules and direct calls to the module
that matches the "tag".

Fastfwd-compatible modules are given tags:

```elixir
defmodule Bread.Barm do

  use Fastfwd.Receiver, tags: [:barm]
  def bake(loaves), do: "Baking #{loaves} of #{__MODULE__}"

end

defmodule Bread.Stottie do

  use Fastfwd.Receiver, tags: [:stottie]
  def bake(loaves), do: "Baking #{loaves} of #{__MODULE__}"

end

defmodule Bread.SlicedWhiteLoaf do

  use Fastfwd.Receiver, tags: [:sliced]
  def bake(loaves), do: "Baking #{loaves} of #{__MODULE__}"

end

defmodule Bread.Sourdough do

  use Fastfwd.Receiver, tags: [:sourdough]
  def bake(loaves), do: "Baking #{loaves} of #{__MODULE__}"

end

```

Another module is configured to act as a forwarder - this is the module
the rest of your code will interact with.

```elixir
defmodule Bread do

  use Fastfwd.Sender, namespace: Bread, cache: true

  def bake(type, loaves) do
    fwd(type, :bake, [loaves])
  end

end

```

You can then call the appropriate module's function via the forwarder

```
Bread.bake(:stottie, 8)
Bread.bake(order.type, order.quantity)
```

You can easily integrate Fastfwd with with Ecto.

To only store records with a type that matches available tags:

```
def changeset(bread_order, params \\ %{}) do
    user
    |> validate_inclusion(:type, Bread.fwd_tags)
    |> cast(params, [:type, :quantity])
    |> validate_required([:type, :quantity])
end
```



## API Documentation

Full documentation can be found at [https://hexdocs.pm/fastfwd](https://hexdocs.pm/fastfwd).


## More Information

https://en.wikipedia.org/wiki/Dynamic_dispatch#Smalltalk_implementation

https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)#Applications

http://charlesleifer.com/blog/django-patterns-pluggable-backends/

## Thanks to

https://edmz.org/personal/2016/02/25/dynamic_function_dispatch_with_elixir.html