Excelから関数型言語マスター4回目:Webに外部APIデータ表示

(この記事は、「Elixir or Phoenix Advent Calendar 2017」の18日目です)

昨日は、@takasehideki さんの「ElixirでIoT#3:IoTボードで動いた!Phoenixが立った!性能評価と考察」でした


fukuoka.ex代表のpiacereです

今回もご覧いただいて、ありがとうございます:bow:

この連載の、前回までの記事は、以下になります

前回までは、fukuoka.ex#8で披露した、マーケティングに強いCTOが語る技術未来とElixir:第2回「プログラミング未経験でもExcelできればElixirマスターできる ~ITのパラダイムシフトで従来の知識・経験が邪魔になる時~」の範疇内でしたが、今回と次回は、このスライドに書かれていない領域について解説します

今回は、まず列名表示を修正した後、「列の抽出」を行い、その後、Web上に外部APIで取得したデータを表示します


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

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

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


lib/sample_db_web/templates/page/index.html.eex

<%

result = Db.query( "select * from members" )
data = result |> Db.columns_rows
columns = result |> Db.columns
%>
<table border="1">
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

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


lib/sample_db_web/templates/page/index.html.eex

<%

result = Db.query( "select * from members" )
data = result |> Db.columns_rows
columns = result |> Db.columns
%>
<table border="1">
<tr>
<%= for column <- columns do %>
<th><%= column %></td>
<% end %>
</tr>
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

以下のような表示になりました

image.png


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

列指定が固定では無くなったので、ここで第2回で行った「列の抽出」をWeb上でも行ってみます

dataから、「name」と「age」の値のみを抽出します


lib/sample_db_web/templates/page/index.html.eex

<%

result = Db.query( "select * from members" )
data = result |> Db.columns_rows
|> Enum.map( fn( record ) -> %{ "name" => record[ "name" ], "age" => record[ "age" ] } end )
columns = result |> Db.columns
%>
<table border="1">
<tr>
<%= for column <- columns do %>
<th><%= column %></td>
<% end %>
</tr>
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

抽出した列の値のみとなりました

image.png

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


lib/sample_db_web/templates/page/index.html.eex

<%

result = Db.query( "select * from members" )
data = result |> Db.columns_rows
columns = result |> Db.columns
|> Enum.filter( fn( column ) -> column == "name" || column == "age" end )
%>
<table border="1">
<tr>
<%= for column <- columns do %>
<th><%= column %></td>
<% end %>
</tr>
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

抽出した列のみとなりました

image.png

下記のように、「columns」に列名を直接指定することもできます


lib/sample_db_web/templates/page/index.html.eex

<%

result = Db.query( "select * from members" )
data = result |> Db.columns_rows
columns = [ "name", "age" ]
%>
<table border="1">
<tr>
<%= for column <- columns do %>
<th><%= column %></td>
<% end %>
</tr>
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

ちなみに、「select文で列指定しない」でも同様の結果にできます(Mnesia版はできません)


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

では今回の本題、外部API呼出を行います

外部API呼出のために、小粒でピリリなユーティリティライブラリ「smallex」を導入するため、mix.exsの「def deps do」配下に追記します(:phoenix~の記載の上行に追加)


mix.exs

defmodule SampleDb.Mixfile do

use Mix.Project

defp deps do
[
{ :smallex, "~> 0.1" },

]
end


Smallexおよび関連ライブラリ一通りを取得します(要ネット接続)

mix deps.get


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

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

SmallexのJsonモジュールを使うと、外部API呼出は、URLのドメインとパスを指定するだけで実行でき、呼出結果もマップリスト化してくれます

更に、「<table~」で始まるHTML部分は、DB表示のものと全く変えていません

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


lib/sample_db_web/templates/page/index.html.eex

<%

result = Json.get( "https://qiita.com", "/api/v2/items?query=elixir" )
data = result
columns = [ "id", "title", "created_at" ]
%>
<table border="1">
<tr>
<%= for column <- columns do %>
<th><%= column %></td>
<% end %>
</tr>
<%= for record <- data do %>
<tr>
<%= for column <- columns do %>
<td><%= record[ column ] %></td>
<% end %>
</tr>
<% end %>
</table>

Qiitaから取得したコラムのID/タイトル/作成日時が表示できました

image.png

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


終わり

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

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

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

次回は、いよいよ派手な領域、「Webにグラフ表示」を行います

あと、Advent Calendarの方、明日は、@tuchiro さんの「ElixirでSI開発入門 #4 本番パスワードを環境変数に持たせる」です