/var/log/messages

Feb 27, 2019 - 2 minute read - Comments - programming

プログラミング Elixir (20)

13.7 変換: レスポンスを加工する、の節。

JSON の加工

poison というライブラリを使う模様。

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},
      { :httpoison, "~> 0.8"},
      { :poison,    "~> 1.5"},
    ]
  end

で、以下を。

$ mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  certifi 2.4.2
  hackney 1.15.0
  httpoison 0.13.0
  idna 6.0.0
  metrics 1.0.1
  mimerl 1.0.2
  parse_trans 3.3.0
  ssl_verify_fun 1.1.4
  unicode_util_compat 0.4.1
A new Hex version is available (0.18.2 < 0.19.0), please update with `mix local.hex`
All dependencies up to date

handle_response を以下にして

  def handle_response({ :ok, %{status_code: 200, body: body}}) do
    { :ok, Poison.parser.parse!(body)}
  end

  def handle_response({ ___, %{status_code: ___, body: body}}) do
    { :error, Poison.parser.parse!(body)}
  end

CLI も修正とのこと。て、13.5 な修正を盛り込んでおりませんでした。。以下な run 手続きを追加して、って思ったらありました。以下に修正。

  def run(argv) do
    argv
    |> parse_args
    |> process
  end

で、process を追加。

  def process(:help) do
    IO.puts """
    usage: issues <user> <project> [ count | #{@default_count} ]
    """
    System.halt(0)
  end

  def process([user, project, _count]) do
    Issues.GithubIssues.fetch(user, project)
  end

なんでこのあたりスルーしたのかと。

$ mix run -e 'Issues.CLI.run(["-h"])'
usage: issues <user> <project> [ count | 4 ]

で、下側のソレを以下に修正。

  def process([user, project, _count]) do
    Issues.GithubIssues.fetch(user, project)
    |> decode_response
  end

  def decode_response({:ok, body}), do: body

  def docode_response({:error, error}) do
    {_, message} = List.keyfind(error, "message", 0)
    IO.puts "Error fetching from Github: #{message}"
    System.halt(2)
  end

これはエラーの時にはこうする、というフィルタなのかな。で、正常系な処理が以下なのか。

  def process([user, project, _count]) do
    Issues.GithubIssues.fetch(user, project)
    |> decode_response
    |> convert_to_list_of_maps
  end

  def decode_response({:ok, body}), do: body

  def docode_response({:error, error}) do
    {_, message} = List.keyfind(error, "message", 0)
    IO.puts "Error fetching from Github: #{message}"
    System.halt(2)
  end

  def convert_to_list_of_maps(list) do
    list
    |> Enum.map(&Enum.into(&1, Map.new))
  end

convert_to_list_of_maps な定義について確認してみます。

Enum とか Map とか

  • Enum.map
  • Enum.info
  • Map.new

について確認を。まず Enum.map/2 ですが以下な記載があります。

Returns a list where each item is the result of invoking fun on each corresponding item of enumerable.

Enum.map/2 に渡されてる手続きが Enum.into/2 ですね。

iex> Enum.into([a: 1, b: 2], %{})
%{a: 1, b: 2}

になるカンジなのか成程。Map.new/0 は上の %{} を作るイメージのはず。

config

アプリケーション設定、ということでハードコードされている github API の URL を設定に保持してみる、とのこと。issues/config/config.exs に以下を追加。

config :issues, github_url: "https://api.github.com"

で、github_issues.exs を以下に、とのこと。

defmodule Issues.GithubIssues do
  @user_agent [ {"User-agent", "Elixir dave@"}]
  @github_url Application.get_env(:issues, github_url:)

  def fetch(user, project) do
    issues_url(user, project)
    |> HTTPoison.get(@user_agent)
    |> handle_response
  end

  def issues_url(user, project) do
    "#{@github_url}/repos/#{user}/#{project}/issues"
  end

あと、アプリケーションの環境 (開発、テスト、本番) に沿った設定、というのもある、とか --config というオプションを渡して云々、という方式もあるようですが、ここではスルーします。

OODA LOOP rake task の引数

comments powered by Disqus