I’m using this module wormwood for absinthe testing. I want to access some attributes dynamiclly.
defmacro query_gql(options \\ []) do
quote do
__MODULE__.__info__(:attributes) |> IO.inspect(label: "info")
# Module.get_attribute(__MODULE__, :_wormwood_gql_query) |> IO.inspect(label: "attr")
unquote(__CALLER__.module).__info__(:attributes) |> IO.inspect(label: "info")
# Code.fetch_docs(__MODULE__) |> IO.inspect(label: "doc")
if is_nil(@_wormwood_gql_query) do
raise WormwoodSetupError, reason: :missing_declaration
end
Absinthe.run(
@_wormwood_gql_query,
@_wormwood_gql_schema,
unquote(options)
)
end
end
when I use Module.get_attribute(__MODULE__, :_wormwood_gql_query) |> IO.inspect(label: "attr")
it returns
** (ArgumentError) could not call Module.get_attribute/2 because the module AwBackendWeb.Schema.Mutation.Project.ProjectTest is already compiled. Use the Module.__info__/1 callback or Code.fetch_docs/1 instead
when I use unquote(__CALLER__.module).__info__(:attributes) |> IO.inspect(label: "info")
Only attributes that are declared with persist: true will be available after the module is compiled:
iex(1)> defmodule Foo do
@not_persisted "not persisted"
Module.register_attribute(__MODULE__, :is_persisted, persist: true)
@is_persisted "is persisted"
end
warning: module attribute @not_persisted was set but never used
iex:2
iex(2)> Foo.__info__(:attributes)
[vsn: [245159702118266867653827558832398806603], is_persisted: ["is persisted"]]
Note that the compiler complains about @not_persisted never being read, since it can’t be accessed post-compilation. There’s no corresponding warning for @is_persisted.
Another simple way to capture the value of a compile-time-only module attribute is to declare a function that returns it:
defmodule Foo do
@not_persisted "not persisted"
Module.register_attribute(__MODULE__, :is_persisted, persist: true)
@is_persisted "is persisted"
def not_persisted() do
@not_persisted
end
end
iex(4)> Foo.__info__(:attributes)
[vsn: [234502421792692061815367290682785245360], is_persisted: ["is persisted"]]
iex(5)> Foo.not_persisted()
"not persisted"