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, the package can be installed
by adding fastfwd to your list of dependencies in mix.exs:
def deps do
[
{:fastfwd, "~> 0.1.0"}
]
endExample
Fastfwd proves an alternative to hardcoding which module should be used for each type of data, for example with a case statement, like this
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)
endFastfwd will find all suitable modules and direct calls to the module that matches the "tag".
Fastfwd-compatible modules are given tags:
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.
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])
endAPI Documentation
Full documentation can be found at 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