How to access attributes dynamically?

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"
5 Likes