LoginSignup
12
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-01-18

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

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

そういったコードは

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

という特徴を持つ.

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

そういったものを

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

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

Gistの制限

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

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

例として,外部ライブラリ HTTPoison を利用した,すぐに実行できるようなサンドボックスを Gist に置く

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

% 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 を追加する.この設定をしないと,mix は lib 以下からソースコードを探してしまうため,ルートディレクトリにあるソースコードを見つけられず,コンパイルエラーになる.

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

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

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

IO.inspect result

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

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へアップロードして完成だ.

に用意した.

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

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

% 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 へ置いておけば,依存ライブラリのバージョンも固定され,より再現しやすい.

12
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6