LoginSignup
5
0

More than 1 year has passed since last update.

志士は溝壑(こうがく)に在るを忘れず、勇士は其の元(かうべ)を喪うことを忘れず

Advent Calendar 2022 131日目1の記事です。
I'm looking forward to 12/25,2022 :santa::santa_tone1::santa_tone2::santa_tone3::santa_tone4::santa_tone5:
私のAdvent Calendar 2022 一覧


はじめに

Elixir を楽しんでいますか:bangbang::bangbang::bangbang:

この記事は、Application.compile_env/3をオススメします。

Compile-time environment

もし

lib/foo.ex
defmodule Foo do
  @moduledoc """
  Documentation for `Foo`.
  """
  @world Application.get_env(:foo, :world, "awesome")

  def hello do
    @world
  end
end

と書いてあるところがありましたら、

lib/foo.ex
defmodule Foo do
  @moduledoc """
  Documentation for `Foo`.
  """
  @world Application.compile_env(:foo, :world, "awesome")

  def hello do
    @world
  end
end

と書くようにしましょう。
違いは、@worldの中身の定義の仕方です。
前者はApplication.get_env/3を、後者はApplication.compile_env/3を使っています。

ということが、Compile-time environment に書いてあります。
@mnishiguchi さんに教えてもらいました :pray::pray_tone1::pray_tone2::pray_tone3::pray_tone4::pray_tone5:

説明が前後しますが、こういうconfig/config.exsもセットで置いてあることが多いとおもいます。

config/config.exs
import Config

config :foo, :world, "awesome123"

注意事項

注意事項をいくつか書きます。

1.10 or later

Elixirのバージョンは1.10以上から、Application.compile_env/3は使えます。

(RuntimeError) Application.compile_env/3 cannot be called inside functions, only in the module body

lib/foo.ex
defmodule Foo do
  def foo do
    Application.compile_env(:foo, :world, "awesome")
  end
end

上記はコンパイルできません。

この場合は、以下のようにApplication.get_env/3を使います。

lib/foo.ex
defmodule Foo do
  def foo do
    Application.get_env(:foo, :world, "awesome")
  end
end

By using compile_env/3, tools like Mix will store the values used during compilation and compare the compilation values with the runtime values whenever your system starts, raising an error in case they differ.

なにもしていないのに壊れた :sob: に近いことが起こるかもしれません。
いや何かしているのです。なにかしているのでERROR!が発生しているのです。

ERROR! the application :foo has a different value set for key :world during runtime compared to compile time. Since this application environment entry was marked as compile time, this difference can lead to different behaviour than expected:

  * Compile time value was set to: "awesome1234"
  * Runtime value was set to: "awesome123"

To fix this error, you might:

  * Make the runtime value match the compile time one

  * Recompile your project. If the misconfigured application is a dependency, you may need to run "mix deps.compile foo --force"

  * Alternatively, you can disable this check. If you are using releases, you can set :validate_compile_env to false in your release configuration. If you are using Mix to start your system, you can pass the --no-validate-compile-env flag


** (ErlangError) Erlang error: "aborting boot"
    (elixir 1.13.1) Config.Provider.boot/2

上記の:foo:worldは適宜読み替えてください。

解決方法は、mix compile --forceとでもすればいいでしょう。
fooが依存しているHexならmix deps.compile foo --forceです。

発生方法は以下の通りです。
もっと実践的な発生方法がわかりましたら追記します。

lib/foo.ex
defmodule Foo do
  @moduledoc """
  Documentation for `Foo`.
  """
  @world Application.compile_env(:foo, :world, "awesome")

  def hello do
    @world
  end
end
config/config.exs
import Config

config :foo, :world, "awesome1234"
config/runtime.exs

config/runtime.exsはとりあえず空のファイルで大丈夫です。
上記の3ファイルがあるプロジェクトにて

iex -S mix

を一旦します。
実行してみます。

iex> Foo.hello
"awesome1234"

という結果が得られました。
config/config.exsを書き換えます。
たとえば

config/config.exs
import Config

config :foo, :world, "awesome123"

そしてrecompileします。

iex> recompile

一旦、Ctl+Cを2回押しでもしてIExを終了させます。
そして再度iex -S mixとすると冒頭のエラーに遭遇できます。

config/runtime.exsが存在しない場合は、同じことをしてもERROR!とはならないです。
もっと実践的なところで遭遇する例をみつけたら追記したいとおもいます。

まとめ

この記事は、Module attributesで、Application.get_env/3を使っている箇所があったら、Application.compile_env/3のほうを使うことがススメられていますよということをご紹介した記事です。

Application.compile_env/3に置き換えたときに遭遇するかもしれない注意事項を3点書きました。

  • 1.10 or later
  • (RuntimeError) Application.compile_env/3 cannot be called inside functions, only in the module body
  • By using compile_env/3, tools like Mix will store the values used during compilation and compare the compilation values with the runtime values whenever your system starts, raising an error in case they differ.

Enjoy Elixir:bangbang::bangbang::bangbang:
$\huge{Enjoy\ Elixir🚀}$

We are the Alchemists, my friends!!!


I organize autoracex.
And I take part in NervesJP, fukuoka.ex, EDI, tokyo.ex, Pelemay.
I hope someday you'll join us.

We Are The Alchemists, my friends!

  1. @kaizen_nagoya さんの「「@e99h2121 アドベントカレンダーではありますまいか Advent Calendar 2020」の改訂版ではありますまいか Advent Calendar 2022 1日目 Most Breakthrough Generator」から着想を得て、模倣いたしました。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0