GistへElixirのプロジェクトを置き，最小限の自己完結した確認可能なコードとして利用する

# どういうときに使うと便利か

外部ライブラリが絡むようなバグの最小再現コード，あるいはすぐに試せるサンプルを置くようなとき．

そういったコードは

1. 今後コミットを重ねていくつもりがあまりない
2. 外部ライブラリに依存を持つ

という特徴を持つ．

1 を考えると，Github のリポジトリとして登録するほどでもない．
2 を考えると，単なるコード片だけだとライブラリのインストールや依存関係を解決できない．

そういったものを

```zsh
% git clone https://example.com/foo.git
% cd foo
foo% mix deps.get
foo% mix run foo.exs
```

といったコマンドを順番に打つだけで内容を再現できると，伝えたい相手が試しやすい．

# Gistの制限

ディレクトリ構造を作れない．
以前は作れたようなのだが，現在はファイルのみを置ける．

# GistへアップロードするElixirのプロジェクトを準備する

例として，外部ライブラリ [HTTPoison](https://github.com/edgurgel/httpoison) を利用した，すぐに実行できるようなサンドボックスを Gist に置く

まずは通常と同じように `mix new foo` し，そこから不要なファイルを削除する．

```zsh
% mix new httpoison_sandbox
% cd httpoison_sandbox/
httpoison_sandbox% ls
README.md  config  lib  mix.exs  test
httpoison_sandbox% rm -rf README.md config lib test
httpoison_sandbox% ls
mix.exs
```
ここで mix.exs の 2 箇所を編集する．

一つは，deps へと依存関係を追加する．これは普通の Elixir プロジェクトでも行っているものだ．

もう一つは，ルートディレクトリにあるソースコードをプロジェクトのソースコードとして利用するため，コンパイルパス [:elixirc_paths](https://hexdocs.pm/mix/1.4.0/Mix.Tasks.Compile.Elixir.html#module-configuration) を追加する．この設定をしないと，mix は `lib` 以下からソースコードを探してしまうため，ルートディレクトリにあるソースコードを見つけられず，コンパイルエラーになる．

```ex:mix.exs
defmodule HttpoisonSandbox.Mixfile do
  use Mix.Project

  def project do
    [app: :httpoison_sandbox,
     version: "0.1.0",
     elixir: "~> 1.4",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     elixirc_paths: ["."], # ソースコードを読み込むパスを変更するため，追加
     deps: deps()]
  end

  def application do
    [extra_applications: [:logger]]
  end

  defp deps do
    [
      {:httpoison, "~> 0.10.0"} # 依存関係を示すため，追加
    ]
  end
end
```

次に実行したいソースコードを新規追加する．

```ex:httpoison_sandbox.exs
HTTPoison.start
result = HTTPoison.get! "http://example.com"

IO.inspect result
```

これで動作させられる最小の構成が完成した．

```zsh
httpoison_sandbox% ls
httpoison_sandbox.exs  mix.exs
httpoison_sandbox% mix deps.get
httpoison_sandbox% mix run
%HTTPoison.Response{body: "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        body {\n            background-color: #fff;\n        }\n        div {\n            width: auto;\n            margin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is established to be used for illustrative examples in documents. You may use this\n    domain in examples without prior coordination or asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n",
 headers: [{"Cache-Control", "max-age=604800"}, {"Content-Type", "text/html"},
  {"Date", "Wed, 18 Jan 2017 13:46:17 GMT"},
  {"Etag", "\"359670651+gzip+ident\""},
  {"Expires", "Wed, 25 Jan 2017 13:46:17 GMT"},
  {"Last-Modified", "Fri, 09 Aug 2013 23:54:35 GMT"},
  {"Server", "ECS (rhv/818F)"}, {"Vary", "Accept-Encoding"}, {"X-Cache", "HIT"},
  {"x-ec-custom-error", "1"}, {"Content-Length", "1270"}], status_code: 200}
```

この2つのファイルをGistへアップロードして完成だ．

https://gist.github.com/niku/1fa19416421214ab78987a6c1e8ae93d

に用意した．

# GistへアップロードしたElixirプロジェクトを利用する

GistへアップロードしたElixirプロジェクトが意図通り利用できるか検証する．

```zsh
% git clone https://gist.github.com/niku/1fa19416421214ab78987a6c1e8ae93d
Cloning into '1fa19416421214ab78987a6c1e8ae93d'...
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
% cd 1fa19416421214ab78987a6c1e8ae93d
1fa19416421214ab78987a6c1e8ae93d% ls
httpoison_sandbox.exs  mix.exs
% mix do deps.get, run httpoison_sandbox.exs
(...snip...)
%HTTPoison.Response{body: "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        body {\n            background-color: #fff;\n        }\n        div {\n            width: auto;\n            margin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is established to be used for illustrative examples in documents. You may use this\n    domain in examples without prior coordination or asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n",
 headers: [{"Cache-Control", "max-age=604800"}, {"Content-Type", "text/html"},
  {"Date", "Wed, 18 Jan 2017 13:59:28 GMT"},
  {"Etag", "\"359670651+gzip+ident\""},
  {"Expires", "Wed, 25 Jan 2017 13:59:28 GMT"},
  {"Last-Modified", "Fri, 09 Aug 2013 23:54:35 GMT"},
  {"Server", "ECS (rhv/818F)"}, {"Vary", "Accept-Encoding"}, {"X-Cache", "HIT"},
  {"x-ec-custom-error", "1"}, {"Content-Length", "1270"}], status_code: 200}
```

準備したときの実行結果とほぼ同じ(時間などを除くと同じ)内容が出力できている．

これで Gist 上に Elixir プロジェクトを置くことができているといえる．

# 再現性の向上(optional)

もしバグの再現コードとして利用する場合は，`mix deps.get` したときに追加される，依存関係を固定するファイル `mix.lock` を含めて，3 ファイルを Gist へ置いておけば，依存ライブラリのバージョンも固定され，より再現しやすい．