ExcelからElixir入門④：Webで外部API表示

【本コラムは、3分で読めて、10分くらいでお試しいただけます】
[piacere](https://twitter.com/piacere_ex)です、ご覧いただいてありがとございます :bow:

[前回](https://qiita.com/piacerex/items/a7558adc6856e3577dc6)は、Web上にDBデータを表示しました

今回は、まず列名表示部分をデータから反映できるようにした後、「列の抽出」を行い、それを応用して外部APIで取得したデータを表示します

**■「ExcelからElixir入門」シリーズの目次**
[**①データ並替え／絞り込み**](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1)
|> [**②データ列抽出、Web表示**](https://qiita.com/piacere_ex/items/b7787580fce5f148242f)
|> [<b>③WebにDBデータ表示</b>](https://qiita.com/piacere_ex/items/a7558adc6856e3577dc6)
|> [<b>④Webに外部APIデータ表示</b>](https://qiita.com/piacere_ex/items/4c212615a4eb699dd109)
|> [<b>⑤Webにグラフ表示</b>](https://qiita.com/piacere_ex/items/290b76b76d5ff8e019bf)
|> [**⑥SPAからPhoenix製APIを呼び出す（表示編）【LiveView版】**](https://qiita.com/piacerex/items/64e77b85bfb4c6832662)
|> [**⑦SPAからPhoenix製APIを呼び出す（更新編）【LiveView版】**](https://qiita.com/piacerex/items/78ee0d2ad8cca0927980)
|> [<b>⑧Gigalixirに本番リリース</b>](https://qiita.com/piacerex/items/1a9cbcc740ca3707eaec)
|> [**⑨ElixirサーバサイドのみでReactと同じSPA／リアルタイムUIが作れる「LiveView」**](https://qiita.com/piacerex/items/3f8ee18c9443d63955bf)
|> [**⑩ElixirサーバサイドSPAをスマホで見るためにGigalixirリリース**](https://qiita.com/piacerex/items/583174d72e6fc0cd289e)
|> [**⑪Gigalixir上のLiveViewアプリに独自ドメイン名を付与して正式なアプリ公開**](https://qiita.com/piacerex/items/b61348c282395167fd8c)
|> [**⑫Elixir／PhoenixのCRUD Webアプリをリリース**](https://qiita.com/piacerex/items/511f24888c7350639d0b)

# データ内にある「列名」で列表示

前回、DBからデータ取得できるようになったのですが、取得したデータ内に「列名」があるので、それを使うと、各列を個別に指定しなくても列表示ができるようになります

columnsに、DBから取得した「列名」を設定し、各列の表示時に、forで出力するように変更します

ついでに、列名を表示する先頭行も追加します

```elixir:lib/basic_web/templates/page/index.html.heex
<%
result = Db.query("select * from members")
datas = result |> Db.columns_rows
columns = result |> Db.columns
%>
<table>
<tr>
  <%= for column <- columns do %>
  <th><%= column %></th>
  <% end %>
</tr>
<%= for n <- datas do %>
<tr>
  <%= for column <- columns do %>
  <td><%= n[ column ] %></td>
  <% end %>
</tr>
<% end %>
</table>
```

以下のような表示になりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/1cdfeaf9-1532-caa8-b45b-fb1adadf4950.png)

# 複数列データの「列の抽出」

列指定が固定では無くなったので、ここで[第2回で行った「列の抽出」](https://qiita.com/piacere_ex/items/b7787580fce5f148242f#%E8%A4%87%E6%95%B0%E5%88%97%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8B%E3%82%89%E5%88%97%E3%81%AE%E6%8A%BD%E5%87%BA)をWeb上でも行ってみます

`datas` から、`name` と `age` の値のみを抽出します

```elixir:lib/basic_web/templates/page/index.html.heex
<%
result = Db.query("select * from members")
datas = result |> Db.columns_rows
  |> Enum.map(fn n -> %{"name" => n["name"], "age" => n["age"]} end)
columns = result |> Db.columns
%>
<table>
<tr>
  <%= for column <- columns do %>
  <th><%= column %></th>
  <% end %>
</tr>
<%= for n <- datas do %>
<tr>
  <%= for column <- columns do %>
  <td><%= n[ column ] %></td>
  <% end %>
</tr>
<% end %>
</table>
```

抽出した列の値のみとなりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/cfb91011-f7bb-1d3c-5004-3c333fa2e771.png)

空の列を消すには、`columns` の方を `name` と `age` のみとなるようフィルタします

```diff_elixir:lib/basic_web/templates/page/index.html.heex
<%
result = Db.query("select * from members")
datas = result |> Db.columns_rows
columns = result |> Db.columns
+ |> Enum.filter(fn n -> n == "name" || n == "age" end)
%>
<table>
<tr>
  <%= for column <- columns do %>
  <th><%= column %></th>
  <% end %>
</tr>
<%= for n <- datas do %>
<tr>
  <%= for column <- columns do %>
  <td><%= n[column] %></td>
  <% end %>
</tr>
<% end %>
</table>
```

抽出した列のみとなりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/703de862-ac70-734f-e488-4c2885ea715e.png)

下記のように、`columns` に列名を直接指定することでもOKです

```diff_elixir:lib/basic_web/templates/page/index.html.heex
<%
result = Db.query("select * from members")
datas = result |> Db.columns_rows
+ columns = ["name", "age"]
%>
<table>
<tr>
  <%= for column <- columns do %>
  <th><%= column %></th>
  <% end %>
</tr>
<%= for n <- datas do %>
<tr>
  <%= for column <- columns do %>
  <td><%= n[column] %></td>
  <% end %>
</tr>
<% end %>
</table>
```

# 外部API呼出のためのライブラリをインストール

外部API呼出を行うためのライブラリ「Req」を、mix.exsの `def deps do` 配下の `:phoenix` の直上に追記します

```diff_elixir:mix.exs
defmodule Basic.Mixfile do
  use Mix.Project
…
  defp deps do
    [
+     {:req, "~> 0.3"}, 

      {:phoenix, "~> 1.7.7"},
      …
    ]
  end
…
```

ライブラリを取得します（要ネット接続）

```sh
mix deps.get
```

# Qiita APIを呼んでQiitaコラム情報をWeb表示する

外部APIとして、Qiitaの検索APIを呼んで、「Elixir」というキーワードが含まれるコラムのリストを取得し、各コラムのID／タイトル／作成日時をWeb表示してみます

`<table>` で始まるHTML部分は、DB表示のものと全く変えていません

つまり、外部APIで取得したデータも、DBと全く同じように扱える点に注目してください

```diff_elixir:lib/basic_web/templates/page/index.html.heex
<%
+ result = Req.get!("https://qiita.com/api/v2/items?query=elixir") |> Map.get(:body)
+ datas = result
+ columns = ["id", "title", "created_at"]
%>
<table>
<tr>
  <%= for column <- columns do %>
  <th><%= column %></th>
  <% end %>
</tr>
<%= for n <- datas do %>
<tr>
  <%= for column <- columns do %>
  <td><%= n[column] %></td>
  <% end %>
</tr>
<% end %>
</table>
```

Qiitaから取得したコラムのID／タイトル／作成日時が表示できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/55316138-7773-3786-a5f8-aa124a19a002.png)

DB表示と同じHTML部分を使いまわしつつ、外部APIデータのWeb表示ができるようになりました

ちなみにQiita APIは何十回が呼び出すと、`Rate Limit` がかかって呼出不可になるので、ページをあまりリロードし過ぎないように注意してください（なお、1時間立つと解除されます）

# 【参考】本コラムの検証環境

本コラムは、以下環境で検証しています（恐らくUbuntu実機やMacでも動きます）

- Windows 10
  - 実機＊Elixir 1.14.2 (Erlang/OTP 25)
    - Phoenix 1.6.15
  - WSL2／Ubuntu 20.04＋Elixir 1.14.2 (Erlang/OTP 25)　※[**最新版のインストール手順はコチラ**](https://qiita.com/piacerex/items/01e89435af0f7a454ad2)
    - Phoenix 1.6.15
  - Docker／Debian 11.6＋Elixir 1.14.2 (Erlang/OTP 25)
    - Phoenix 1.6.15

- Windows11
  - WSL2／Ubuntu 22.04＋Docker Compose＋Elixir 1.13.4 (Erlang/OTP 25)
    - Phoenix 1.6.15

# 終わり

いかがでしたでしょうか、Web＋APIも、Web＋DB同様、とても簡単に実現できました

データ元が、DBだろうが、外部APIだろうが、内部変数だろうが、全てマップリストになってしまうので、画面側は一切、修正が必要ありませんでした

こうした関数型言語によるWeb開発の威力を実感いただけたら幸いです

[次回は、いよいよ派手な領域、**Webにグラフ表示** を行います](https://qiita.com/piacere_ex/items/290b76b76d5ff8e019bf)