Skip to content

Instantly share code, notes, and snippets.

@am-kantox
Last active October 31, 2018 09:08
Show Gist options
  • Save am-kantox/06903bfee9634cf7909128787a559d9f to your computer and use it in GitHub Desktop.
Save am-kantox/06903bfee9634cf7909128787a559d9f to your computer and use it in GitHub Desktop.
Updating guard module
defmodule Validator do
def instance!(rules, merge \\ true) do
mod = Module.concat(["Validator", "Instance"])
current_rules =
if Code.ensure_compiled?(mod) do
rules = if merge, do: apply(mod, :rules, []), else: %{}
:code.purge(mod)
:code.delete(mod)
rules
else
%{} # no previous rules
end
Module.create(mod, ast(rules, current_rules), Macro.Env.location(__ENV__))
end
defp ast(rules, current_rules) do
rules = Map.merge(current_rules, rules) # the latter takes precedence
[
quote do
def valid?(_), do: :error
def rules(), do: unquote(Macro.escape(rules))
end |
Enum.map(rules, fn {pair, %{min: min, max: max}} ->
quote do
def valid?(%{currency_pair: unquote(pair), rate: rate})
when rate > unquote(min) and rate < unquote(max),
do: {:ok, rate}
end
end)
] |> :lists.reverse()
end
end
iex|1 ▶ Validator.instance!(%{"USDEUR" => %{min: 1.0, max: 2.0}})
iex|2 ▶ Validator.Instance.valid?(%{currency_pair: "USDEUR", rate: 1.5})
#⇒ {:ok, 1.5}
iex|3 ▶ Validator.Instance.valid?(%{currency_pair: "USDGBP", rate: 1.5})
#⇒ :error
iex|4 ▶ Validator.instance!(%{"USDGBP" => %{min: 1.0, max: 2.0}})
iex|5 ▶ Validator.Instance.valid?(%{currency_pair: "USDEUR", rate: 1.5})
#⇒ {:ok, 1.5}
iex|6 ▶ Validator.Instance.valid?(%{currency_pair: "USDGBP", rate: 1.5})
#⇒ {:ok, 1.5}
iex|7 ▶ Validator.Instance.rules
#⇒ %{"USDEUR" => %{max: 2.0, min: 1.0}, "USDGBP" => %{max: 2.0, min: 1.0}}
iex|8 ▶ Validator.instance!(%{"USDEUR" => %{min: 1.0, max: 2.0}}, false)
iex|9 ▶ Validator.Instance.rules
#⇒ %{"USDEUR" => %{max: 2.0, min: 1.0}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment