LoginSignup
12
6

More than 3 years have passed since last update.

ElixirでHTTPリクエスト

Posted at

fukuoka.exのkoyoです
最近Goばっかり書いているのでそろそろElixirするかということで書いてみます!

お題

Github API を使って特定のリポジトリのcloseされたPR一覧を出してみる

プロジェクトの作成

mix new sample_ex

必要なライブラリの追加

今回はHTTPリクエストにHTTPoison, レスポンスボディのパースにPoisonを使います

mix.exs
defp deps do
    [
      {:httpoison, "~> 1.5"},
      {:poison, "~> 4.0"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end

実装

対象リポジトリは昔作ったグラフ付きQiita検索アプリ
https://github.com/koyo-miyamura/vue_api_spa

sample_ex.ex
defmodule SampleEx do
  @moduledoc """
  Documentation for SampleEx.
  """

  @spec main :: :ok
  def main() do
    pr_list() |> Enum.each(fn x -> IO.puts(x) end)
  end

  @spec pr_list :: charlist()
  def pr_list() do
    build_url("https://api.github.com/repos/koyo-miyamura/vue_api_spa/pulls", %{
      "state" => "closed"
    })
    |> HTTPoison.get!()
    |> Map.get(:body)
    |> Poison.decode!()
    |> Enum.map(fn x -> format(x) end)
  end

  @doc """
  build url.

  ## Examples

      iex> SampleEx.build_url("http://example.com", %{"foo" => "bar"})
      "http://example.com?foo=bar"

  """
  @spec build_url(String.t(), map()) :: String.t()
  def build_url(path, query) do
    URI.parse(path)
    |> Map.put(:query, URI.encode_query(query))
    |> URI.to_string()
  end

  @doc """
  format map

  ## Examples

      iex> SampleEx.format(%{"title" => "title", "created_at" => "2018-10-06T23:46:53Z"})
      "title 2018-10-06"
  """
  @spec format(map()) :: String.t()
  def format(map) do
    map_title = Map.get(map, "title")

    map_date =
      Map.get(map, "created_at")
      |> NaiveDateTime.from_iso8601!()
      |> NaiveDateTime.to_date()
      |> Date.to_string()

    map_title <> " " <> map_date
  end
end

Elixirで時刻扱うのはちょっとクセありますがこんな感じで
https://hexdocs.pm/elixir/NaiveDateTime.html#content

またURI文字列を作成する部分はURIモジュールを使えば良いですが、クエリパラメータを結合する関数は用意されていなかったので以下を参考に自前で作ってみました
https://stackoverflow.com/questions/49508509/idiom-to-construct-a-uri-with-a-query-string-in-elixir

実行結果


キタ━(゚∀゚)━! $ iex -S mix
Erlang/OTP 21 [erts-10.3.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.8.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> SampleEx.main
ユーザランキング 2018-10-06
vuexの導入 2018-10-06
チャート機能の実装 2018-10-06
Tag search 2018-10-05
Fix design 2018-10-04
Use vue cli 2018-09-30
vue-routerの導入 2018-09-29
Use component 2018-09-26
formから検索ワード変更する機能の追加 2018-09-25
見た目の調整 2018-09-24

できたぜ!!

テストについて

できる部分はdoctestしましたが、HTTPリクエストを行うpr_listのテストはどうするのか分からず断念
Goだとnet/http使ってモックするやり方が考えられますが、Elixirはモックを推奨していない様子

探してみると自前でサーバ立てるやり方が書いてました
んーちょっと大変?もっといいやり方募集中です
https://medium.com/flatiron-labs/rolling-your-own-mock-server-for-testing-in-elixir-2cdb5ccdd1a0

ちなみにHTMLをパースしたい場合

Flokiというライブラリがメジャーみたいです
mix.exs{:floki, "~> 0.21.0"}
すると使えます

感想

最近Goばっかり書いてたんですが「GoでやるアレElixirでどうするんだろう?」という題材で学習してみると学びが深まりました
iex使って動かしながら作れるので楽しい
皆さんも普段使っている言語でやっていることをElixirで実現してみると面白いですよ!

12
6
1

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