コンパイル時に外部ファイルなどからデータを取ってきて,それを元にStructなりMapなりを生成して実行ファイルに混ぜ込みたいということがあります.
そういうときは以下のようにすれば良いです:
sample.ex
defmodule Hoge do
defmacro generate_map do
map = File.read!("./sample.json") |> Poison.decode!
Macro.escape(map)
end
end
defmodule Sample1 do
require Hoge
def cached_file do
Hoge.generate_map
end
def main do
IO.inspect(Sample1.cached_file)
end
end
iex(1)> Sample1.main
%{"age" => 34, "name" => "John Smith"}
%{"age" => 34, "name" => "John Smith"}
generate_struct
の最後にある Macro.escape(map)
がミソで,これによってMapをASTに変換して実行ファイルに埋め込んでいます.
もちろん map = File.read!("./sample.json") |> Poison.decode!
の部分には好きな処理を書くことができます.
例えばJSON APIのリクエストを叩いてその結果を埋め込むこともできます:
sample.ex
defmodule Fuga do
defmacro generate_map do
HTTPoison.start
map = HTTPoison.get!("https://jsonplaceholder.typicode.com/todos/1").body |> Poison.decode!
Macro.escape(map)
end
end
defmodule Sample2 do
require Fuga
def cached_http_call do
Fuga.generate_map
end
def main do
IO.inspect(Sample2.cached_http_call)
end
end
iex(1)> Sample2.main
%{
"completed" => false,
"id" => 1,
"title" => "delectus aut autem",
"userId" => 1
}
%{
"completed" => false,
"id" => 1,
"title" => "delectus aut autem",
"userId" => 1
}