13章の続き。
さて、GitHubのAPIからJSONが返ってきているので、これを処理してやる必要がある。
JSONのライブラリとしてはpoisonを使うみたい。 hex.pmに行って検索し、depsの記述をコピってmix.exsに入れる。
P.156の記述を元に、Issues.GithubIssues.handle_responseを修正する。ここで、
def handle_response({_, %{status_code: status_code, body: body}}) do { status_code |> check_for_error(), body |> Poison.Parser.parse!() } end
のようにしてるんだけど、これはwarningが出る。
warning: Poison.Parser.parse!/1 is undefined or private. Did you mean one of: * parse!/2 lib/issues/github_issues.ex:17: Issues.GithubIssues.handle_response/1
parse!には引数が2つ必要だと言ってるんだけど、それがwarningなのがよくわからない。 実行時エラーになるのかな?このままにしておいてみよう。
ちなみに、2つ目の引数にはパースのオプションを入れるみたい。何も指定しないなら%{}
を渡す。
%{keys: :atoms!}
を渡すと、戻ってくるマップのキーがアトムになる。でも、この!
は何だろう?
Poisonのドキュメントにこう注釈してある
Note that
keys: :atoms!
reuses existing atoms, i.e. if:name
was not allocated before the call, you will encounter an argument error message.
「keys: :atoms!
はアトムを再利用する。例えば、:name
がそれ以前に使われてなければ、エラーになる」・・・なるほど?
You can use the
keys: :atoms
variant to make sure all atoms are created as needed. However, unless you absolutely know what you’re doing, do not do it. Atoms are not garbage-collected, see Erlang Efficiency Guide for more info
「keys: :atoms
を使うこともできるが、全てのアトムが必要になった時点で作られる。これが意味するところを完全に理解していないならば、これを使うべきではない。アトムは決してGCされないから」。な、なるほど。しかし、JSONのキーに出てくる名前の全部のアトムを使うことがそんなに問題なのかな?
本ではここでちょっと寄り道。ソースコードにハードコードしたGitHubのURLをconfig.exsへ出すのだと。ふむふむ。
mix new で新しいプロジェクトを作ったとき、config/ というディレクトリが作られたのを 思い出してほしい。config ディレクトリには、config.exs というファイルが含まれていた。 このファイルは、アプリケーションレベルの設定だ。
アレ?私の手元には作られてないんだけど?
ググってみると、これは1.9での変更らしい。
まず、
mix new
でconfig/config.exs
をつくらなくなりました。設定ファイルに依存することは、ライブラリやその作者にとって望ましくないとされてきたからです。つぎに、mix new --umbrella
は、子アプリケーションごとの設定はつくりません。すべての設定は、アンブレラプロジェクトのルートで宣言することになります。理由については「No longer generate config for mix new」をご参照ください。
ふむ・・・
use Mix.Config
はやわらかな非推奨(soft-deprecated)となります。これからは、Elixirに新たに備わったConfigモジュールをimport Config
としてお使いください。
ここは後でフォローするとして、いったんは本の通りにしてみようかな。
> mkdir config > echo "use Mix.Config" > config/config.exs
これで良いのかな?
これで、P.157の通りにconfig.exsとgithub_issues.exを修正。
実行してみよう。
> iex -S mix Erlang/OTP 23 [erts-11.1.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Compiling 3 files (.ex) warning: Poison.Parser.parse!/1 is undefined or private. Did you mean one of: * parse!/2 lib/issues/github_issues.ex:18: Issues.GithubIssues.handle_response/1 Generated issues app Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> Issues.GithubIssues.fetch("elixir-lang", "elixir") ** (UndefinedFunctionError) function Poison.Parser.parse!/1 is undefined or private. Did you mean one of: * parse!/2 (poison 4.0.1) Poison.Parser.parse!("{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest\"}") (issues 0.1.0) lib/issues/github_issues.ex:18: Issues.GithubIssues.handle_response/1
あー、やっぱり実行時エラーになった。
というわけで、
body |> Poison.Parser.parse!(%{})
のように引数を足す。 これでOK。
後は、Issues.CLI.processにソートと指定の件数だけ取り出す機能を追加する。 これは本の通りにやって、特に不明なところはない。