Reputation: 11251
How could I pass adapter
parameter dynamically to Nebulex.Cache module initialization?
defmodule MyApp.RedisCache do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: if true do NebulexRedisAdapter else Nebulex.Adapters.Nil end
end
Upvotes: 0
Views: 186
Reputation: 121010
The easiest way would be to move the conditional one level up.
defmodule MyApp.RedisCache do
if true do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: NebulexRedisAdapter
else
use Nebulex.Cache,
otp_app: :nebulex,
adapter: Nebulex.Adapters.Nil
end
...
end
Another way would be to create a private macro with a parameter, or, alternatively, create a module attribute storing the adapter
and pass it to use
(assuming Nebulex.Cache
does Macro.expand/2
arguments in the __CALLER__
context.)
The reason is that the macro receives the AST, so what will __using__/1
receive, is quote do: if ....
which won’t be even attempted to compile at the first compilation stage.
The below code might shed a light on how the AST is passed between calls and what Macro.expand/2
does.
defmodule M do
@param if(true, do: M1, else: M2)
defmacrop t1(arg: args) do
IO.inspect(args, label: "#1")
end
defmacrop t2(arg: args) do
IO.inspect(Macro.expand(args, __CALLER__), label: "#2")
end
def test do
t1(arg: if(true, do: M1, else: M2))
t2(arg: if(true, do: M1, else: M2))
t1(arg: @param)
t2(arg: @param)
end
end
It results in:
#1: {:if, [line: 19],
...
#2: {:case, [optimize_boolean: true],
...
#1: {:@, [line: 21], [{:param, [line: 21], nil}]}
#2: M1
Note, that if
was expanded to case
, and the module attribute was not expanded unless the explicit Macro.expand/2
was called on it.
Upvotes: 1