naoya@githubさんの記事を試すには

naoya@githubさんが最近「**カッとなって**」Elixir関連の記事を投稿されていますが、さらにカッとなって[WEB+DB PRESS](http://gihyo.jp/magazine/wdpress/archive/2015/vol88)に記事を書かれています。

でも、あのソースを見てもそのままでは実際に動かせなかった人も多いのでは。次号以降に補足が出るにしても隔月刊ですしね…

ということで復習も兼ねて動かし方を書いてみます。

#### ソース ####

ソースはこんな感じでした(写経)。一つ目の「あまりElixirらしくない」ものを対象にしました。

```ex
defmodule WeatherClient do
  def fetch_json(url) do
    HTTPoison.start
    res = HTTPoison.get!(url)
    Poison.decode!(res.body)
  end

  def get do
    %{"weather" => weather} = fetch_json(
      "http://api.openweathermap.org/data/2.5/weather?q=Tokyo.jp"
    )
    weather
  end
end

Enum.each WeatherClient.get, fn(w) ->
  IO.puts w["main"]
end
```

#### 依存性のあるライブラリ ####

ここでは２つの依存性のあるライブラリが使われています[^1]。
[^1]: Elixirがそもそも「霊薬」なのでもじって薬やら毒関係の名前のライブラリが多いような気がします。

[**HTTPoison**](https://github.com/edgurgel/httpoison)
HTTPクライアントライブラリ。**Erlang**のHTTPクライアントライブラリ[**hackney**](https://github.com/benoitc/hackney)をベースに作られている。[以前に使いました](http://qiita.com/HirofumiTamori/items/602d9b326cb4816c2fe6)。プロキシ設定が使えるのがうれしいケースもあり。
[**Poison**](https://github.com/devinus/poison)
JSONライブラリ。Githubによれば単純さや完全さや正確さを全く犠牲にせず爆速、とのこと。

ですので、これらをどうにかして持ってきて使う必要があります。

#### mix new でプロジェクトを作り mix.exsを設定する ####

ではmixでプロジェクトを作ります。

```bash
$ mix new weatherclient --module WeatherClient
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/weatherclient.ex
* creating test
* creating test/test_helper.exs
* creating test/weatherclient_test.exs

Your mix project was created successfully.
You can use mix to compile it, test it, and more:

    cd weatherclient
    mix test

Run `mix help` for more commands.

```

`--module WeatherClient`を付けたのはモジュール名をCamelCase(WeatherClient)にしたかったから。付けないとWeatherclientになります(そうなると写経したプログラムの方も合わせる必要があるのでめんどくさい)。
次に依存関係のあるライブラリを使うために`mix.exs`を変更します。

```bash
$ cd weatherclient
$ ls
config  lib  mix.exs  README.md  test
$ vi mix.exs
```

(おっと、Vimmerなのがバレてしまった)お好みのエディタでmix.exsを以下のように変更します。

```exs
defmodule WeatherClient.Mixfile do
  use Mix.Project

  def project do
    [app: :weatherclient,
     version: "0.0.1",
     elixir: "~> 1.0",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [applications: [:logger]]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type `mix help deps` for more examples and options
  defp deps do
    [
      {:httpoison, "~> 0.6"},
      {:poison, "~> 1.4.0"}
    ]
  end
end
```
`defp deps do`のところがもともと`[]`になっているのでここに必要なライブラリ名とバージョン(`~>`は...以上の意)を設定します。

#### mix deps.getで必要なものを落としてくる ####

`mix deps.get`で必要なライブラリを落としてきましょう。

```bash
$ mix deps.get
Running dependency resolution
Dependency resolution completed successfully
  hackney: v1.3.1
  httpoison: v0.7.2
  idna: v1.0.2
  poison: v1.4.0
  ssl_verify_hostname: v1.0.5
* Getting httpoison (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/httpoison-0.7.2.tar)
...(中略)...
* Getting idna (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/idna-1.0.2.tar)
Using locally cached package
Unpacked package tarball (/home/azureuser/.hex/packages/idna-1.0.2.tar)
```

次は`lib/webclient.ex`が最初は

```ex
defmodule WeatherClient do
end
```

という内容だけなのでこのファイルに「写経」します。

#### ビルドして実行する ###

`mix run`を実行します。

```bash
$ mix run
==> idna (compile)
Compiled src/idna.erl
...(中略)...
Compiled src/hackney_connect/hackney_cacerts.erl
Compiled src/hackney_lib/hackney_mimetypes.erl
==> httpoison
Compiled lib/httpoison/base.ex
Compiled lib/httpoison.ex
Generated httpoison app
Clouds
==> weatherclient
Compiled lib/weatherclient.ex
Generated weatherclient app
```

おしまいの方にちょろっと
`Clouds`(曇り)
と出てるのが結果です。

2回めからは

```bash
$ mix run lib/weatherclient.ex
```

と実行してください。

```bash
lib/weatherclient.ex:1: warning: redefining module WeatherClient
Clouds
```

と結果の前に警告が出ますが気にしなくていいようです。

#### iex -S mixを使う ####

プログラムが実際何をやっているか見るには`iex`を使いましょう。

```bash
$ iex -S mix
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
```

ここでモジュールWeatherClientの関数を直に叩くと

```iex
iex(1)> WeatherClient.get
[%{"description" => "overcast clouds", "icon" => "04n", "id" => 804,
   "main" => "Clouds"}]
```

という中身が返ってきていることがわかります[^2]。元のプログラムの一番下3行はこの結果の中からキー"main"の値の部分だけ取り出していたのです。続けて確認しましょう。

[^2]: mapのlistです。


```iex
iex(2)> Enum.each WeatherClient.get, fn(w) ->
...(2)>   IO.puts w["main"]
...(2)> end
Clouds
:ok
iex(3)>
```