mmag

ハマったことメモなど

Mixプロジェクトに同梱したファイルを参照する

ある新しいライブラリに以下の問題があってムムッと思ってプルリクした。

例えばlib/data/people.ymlを置くとする。lib/my_app/module.exでこのファイルを読みたい。

# ダメな例
"lib/data/people.yml" |> File.open

# 良い例
"../lib/data/people.yml" |> Path.expand(__DIR__) |> File.open

上の例がなんでマズイかというと、ライブラリとして利用されたときに"../lib/data/people.yml"の"lib"が指しているのは、

another_project
 ├mix.exs
 ├config
 ├lib ← これであって
 │ ├another_project.ex
 │ └another_project
 ├deps
 │ └my_app
 │    └lib ← これではない
 │       └data
 │          └people.yml
 └test

のだ。

なので後者のように、1回フルパスに展開してから使ったほうがよい。単体でテストしても気付きにくいかも。もっと良い方法があるかもしれない。

別ファイルに分けるほど大きなデータとかを使うことがなかったので初遭遇問題だった。 ただ文字列を返すだけの関数をつくったことはあったが、Elixir.String.Unicodeみたいにコンパイル時にファイルを読んで関数定義しちゃうのがパフォーマンス的にも良さそう。

はー、麻婆ナントカ食べたい。

追記

どうやらApplicaiton.app_dir :my_app"/abs/path/to/_build/dev/lib/my_app"が取れるっぽ。ソースからの相対パスだと、ディレクトリ構成変えたとき面倒だし、同じものを読みたいのにソースファイル毎に異なる指定になる。なので良い子はApplication.app_dir/1を使おう。

そして相変わらず麻婆ナントカ食べたい。