諸般の事情により mix.exs の中で設定しているバージョン番号をコントローラから取得するニーズがあってちょっと調べてみたんですが、残念ながら直接そういう機能が無かったため、簡単なマクロで実現してみました。
ロジックは非常に単純で、mix.exs と同じ場所に VERSION
というファイルを置き、その中にバージョン番号を記入するだけです。
コンパイル時にこの値を読み込んで、モジュールの中に version()
という関数を動的に生成してくれるので、あとは mix.exs あるいはコントローラの好きな場所で呼び出すだけです。
1.2.3
defmodule Foo.Mixfile do
use Mix.Project
########## ここから追加
version = File.stream!("VERSION", [], :line)
|> Enum.at(0)
|> String.strip()
def version(), do: unquote(version)
########## ここまで追加
def project do
[app: :foo,
version: version(), ##### ← version()に変更
elixir: "~> 1.3",
elixirc_paths: elixirc_paths(Mix.env),
compilers: [:phoenix, :gettext] ++ Mix.compilers,
build_embedded: (Mix.env == :stg) or (Mix.env == :prod),
start_permanent: (Mix.env == :stg) or (Mix.env == :prod),
aliases: aliases,
deps: deps]
end
・コントローラからバージョンを取得する時用の関数
defmodule Foo.util do
version = File.stream!("VERSION", [], :line)
|> Enum.at(0)
|> String.strip()
def version(), do: unquote(version)
end
本当は DRY にしたかったんですが、mix.exs から他のモジュール(上記の例だと Foo.util.version
)の関数を呼び出しても、おそらく優先度の関係でモジュールを見つけることができずエラーになってしまいました。
その逆に Foo.Mixfile モジュール
の中の関数を Foo.util.version()
から呼ぼうとしても、まぁ当たり前ですがリリースビルド版では * (UndefinedFunctionError) function Foo.Mixfile.version/0 is undefined (module Foo.Mixfile is not available)
になってしまいました。
まぁロジックも短いので気にしないことにします(いい解決方法をご存知の方、ぜひコメントを!)