Packages
maru
0.12.4
0.14.0-pre.1
0.13.2
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
REST-like API micro-framework for elixir inspired by grape.
Current section
Files
Jump to
Current section
Files
lib/maru/builder/extend.ex
defmodule Maru.Builder.Extend do
@moduledoc false
@doc """
Take routes by an extended module.
"""
def take_extended(_, nil), do: []
def take_extended(routes_new, {v_new, opts}) do
module = opts |> Keyword.fetch!(:at)
v_old = opts |> Keyword.fetch!(:extend)
only = opts |> Keyword.get(:only, nil)
except = opts |> Keyword.get(:except, nil)
'Elixir.' ++ _ = Atom.to_charlist module
unless is_nil(only) or is_nil(except) do
raise ":only and :except are in conflict!"
end
module.__routes__
|> Enum.filter(fn route ->
(route.version == v_old) and getable?(routes_new, route)
end)
|> Enum.filter(func(only, except))
|> Enum.map(fn route ->
%{route | version: v_new}
end)
end
defp func(nil, nil), do: fn _ -> true end
defp func(only, nil), do: fn route -> route_match?(only, route) end
defp func(nil, except), do: fn route -> not route_match?(except, route) end
defp getable?(routes, route_extended) do
Enum.all?(routes, fn route ->
route.method != route_extended.method or do_getable?(route.path, route_extended.path)
end)
end
defp do_getable?([], []), do: false
defp do_getable?([h1|_], [h2|_])
when is_binary(h1) and is_atom(h2), do: true
defp do_getable?([h|t1], [h|t2]), do: do_getable?(t1, t2)
defp do_getable?(_, _), do: true
defp route_match?(conds, route) do
Enum.any?(conds, fn {method, path} ->
path = Maru.Builder.Path.split(path)
method_match?(route.method, method) and path_match?(route.path, path)
end)
end
defp method_match?(_m, :match), do: true
defp method_match?(m1, m2) do
m1 == m2 |> to_string |> String.upcase
end
defp path_match?([{:version}|t1], t2), do: path_match?(t1, t2)
defp path_match?([], []), do: true
defp path_match?(_rest, ["*"]), do: true
defp path_match?([h|t1], [h|t2]), do: path_match?(t1, t2)
defp path_match?([_|t1], [h|t2]) when is_atom(h), do: path_match?(t1, t2)
defp path_match?(_, _), do: false
end