【PostgreSQL or MySQL版】ExcelからElixir入門③：WebにDBデータ表示

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

今回は、DBMSをインストールした後、Web上にDBデータを表示します

**■「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)
|> [<b>⑥Vue.js＋内部API（表示編）</b>](https://qiita.com/piacere_ex/items/50d847170291c41fef64)
|> [<b>⑦Vue.js＋内部API（更新編）</b>](https://qiita.com/piacerex/items/7cd1162ce6d66a334a07)
|> [<b>⑧Gigalixirに本番リリース</b>](https://qiita.com/piacerex/items/1a9cbcc740ca3707eaec)
|> [**⑨Elixir／PhoenixのCRUD Webアプリをリリース**](https://qiita.com/piacerex/items/511f24888c7350639d0b)
|> [**⑩「LiveView」ElixirサーバサイドのみでReact的SPA／リアルタイムUIが作れる**](https://qiita.com/piacerex/items/3f8ee18c9443d63955bf)
|> [**⑪LiveView製Qiita検索SPAをフォームsubmitスタイルに換装**](https://qiita.com/piacerex/items/21b0e308a36e486d8b25)
|> [**⑫LiveViewのコード内HTMLをテンプレートファイルに分離**](https://qiita.com/piacerex/items/5b1aabb0c45bb9934bb9)
|> [**⑬ElixirサーバサイドSPAをスマホで見るためにGigalixirリリース**](https://qiita.com/piacerex/items/583174d72e6fc0cd289e)
|> [**⑭Gigalixir上のLiveViewアプリに独自ドメイン名を付与して正式なアプリ公開**](https://qiita.com/piacerex/items/b61348c282395167fd8c)

# DBのインストール

まずは、DBサーバをインストールします

ここでは、DBサーバとして、「PostgreSQL」か「MySQL」のいずれかをインストールすることとします

![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/6c24ba27-835d-809a-b7b7-bb79836b65c1.png)

パスワードは、PostgreSQLは「postgres」、MySQLは未設定（空文字列）で設定しておくと、Phoenix PJ作成後に設定変更が不要になります

※下記リンク先コラムの中には、「パスワードの weak 評価はダメ」といった記載ありますが、本番環境の構築をしている訳では無いので構いません

## ①PostgreSQLのインストール

![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/5ce639ea-d036-d50f-f0c4-9389a0e9e548.png)

下記OS毎のインストール手順を実施してください

Windows：https://eng-entrance.com/postgresql-download-install
macOS：https://qiita.com/okame_qiita/items/ac7b6a7d96d07ecbc50b
Ubuntu：https://qiita.com/eighty8/items/82063beab09ab9e41692
CentOS 7：https://weblabo.oscasierra.net/postgresql10-centos7-install/
CentOS 6：https://weblabo.oscasierra.net/postgresql-installing-postgresql9-centos6-1/

なおUbuntuの場合、インストール直後のpostgresユーザのパスワードを下記SQLで設定し、PostgreSQLを再起動する必要があります

```sql
sudo -u postgres psql
ALTER USER postgres WITH PASSWORD 'postgres';
exit
```

## ②MySQLのインストール

![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/a60e12bd-f2c7-d04e-ee24-1f225a1b8a6e.png)

下記OS毎のインストール手順を実施してください

Windows：https://qiita.com/KeisyaRinco/items/c3074d8450cad96f7e4f
macOS：https://qiita.com/griffin3104/items/c7908359a3e3e18cd269
Ubuntu：https://www.server-world.info/query?os=Ubuntu_16.04&p=mysql
CentOS 7：https://enomotodev.hatenablog.com/entry/2016/09/01/225200
CentOS 6：https://qiita.com/UmedaTakefumi/items/924cdce7cfff083bf492

# DBを使うPhoenixのPJ作成、DB作成、起動

DBを使うPhoenixプロジェクトを作成する際は、[前回のPhoenix PJ作成時](https://qiita.com/piacere_ex/items/b7787580fce5f148242f#phoenix%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%ABpj%E4%BD%9C%E6%88%90%E8%B5%B7%E5%8B%95)に指定していた、「--no-ecto」の指定は行いません

あと、PostgreSQLの場合は、DB指定不要ですが、MySQLの場合は、DB指定が必要です

```:※PostgreSQLの場合
mix phx.new sample_db --no-webpack
Fetch and install dependencies? [Yn] （←n、Enterを入力）
…
```

```:※MySQLの場合
mix phx.new sample_db --database=mysql
Fetch and install dependencies? [Yn] （←n、Enterを入力）
…
```

パスワードを、以下以外で設定している場合は、config/dev.exsの「password」項目の修正が必要です

- PostgreSQL：postgres
- MySQL：未設定（空文字列）

```exs:config/dev.exs　※PostgreSQLの場合
…
# Configure your database
config :sample_db, SampleDb.Repo,
  username: "postgres",
  password: "postgres",
  database: "sample_db_dev",
  hostname: "localhost",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10
```

```exs:config/dev.exs　MySQLの場合
…
# Configure your database
config :sample_db, SampleDb.Repo,
  username: "root",
  password: "",
  database: "sample_db_dev",
  hostname: "localhost",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10
```

PJフォルダに入り、DBを作成します　<font color="red">※作成しないとiex内でエラー連発となるのでお忘れなく</font>

```
cd sample_db
mix ecto.create
```

Phoenixを起動します

```
iex -S mix phx.server
```

ブラウザで「```http://localhost:4000```」にアクセスすると、Phoenixで作られたWebページが見れます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/50548738-9fe7-71f2-2b4f-625b28cc5ea5.png)

# 複数列データと同じ構造のテーブル作成、データ投入

テーブル作成のため、各DBクライアントを実行します

PostgreSQLクライアントの場合、「psql」コマンドを入力し、パスワード入力します

```:※PostgreSQLの場合
psql -U postgres

Password for user postgres:
psql (10.1)
Type "help" for help.

postgres=#
```

MySQLクライアントの場合は、「mysql」コマンドを入力し、パスワード入力します

```:※MySQLの場合
mysql

Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.22-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

アクセス先DBを「sample_db_dev」に変更するため、以下を入力します

```:※PostgreSQLの場合
postgres=# \c sample_db_dev
```

```:※MySQLの場合
mysql> use sample_db_dev
```

前回の複数列データと同じデータ構造のテーブルを作成するため、以下をpsql／mysql内で入力します

```sql
create table members
(
  id integer, 
  name varchar(255), 
  age integer, 
  team varchar(255), 
  position varchar(255) 
);
```

続けて、以下でデータ投入するため、以下をpsql／mysql内で入力します

```sql
insert into members values( 1, 'enぺだーし', 54, '有限会社デライトシステムズ', '代表取締役、性能探求者' );
insert into members values( 2, 'ざっきー', 50, '公立大学法人 北九州市立大学', '准教授、カーネルハッカー' );
insert into members values( 3, 'たくと', 40, 'カラビナテクノロジー株式会社', 'リードエンジニア、アプリマイスター' );
insert into members values( 4, 'piacere', 48, '株式会社DigiDockConsulting', '常務取締役CTO、技術顧問、重力プログラマ' );
```

以下を入力して、各DBクライアントを終了します

```:※PostgreSQLの場合
postgres=# \q
```

```:※MySQLの場合
mysql> exit
```

# DBアクセスモジュールを作る

PJフォルダ内のlibフォルダ配下にutilフォルダを掘り、DBアクセスする以下モジュールを作ります

なお、ここではSQLをそのまま実行できるよう本モジュールを作りますが、実際のPJだとSQLインジェクションの原因となってしまうため、Ecto DSLを使うようにしてください

```elixir:lib/util/db.ex
defmodule Db do
  def query(sql) when sql != "" do
    {:ok, result} = Ecto.Adapters.SQL.query(SampleDb.Repo, sql, [])
    result
  end
  def columns_rows(result) do
    result
    |> rows
    |> Enum.map(fn row -> Enum.into(List.zip([columns(result), row]), %{}) end)
  end
  def rows(%{rows: rows} = _result), do: rows
  def columns(%{columns: columns} = _result), do: columns
end
```

# DBデータをWeb表示

さて、準備が整いましたので、DBデータをWeb表示してみます

以下のように、Webページの元となるファイルを書き換えます

```elixir:lib/basic_db_web/templates/page/index.html.heex
<%
datas = Db.query("select * from members") |> Db.columns_rows
%>
<table>
<%= for n <- datas do %>
<tr>
  <td><%= n["name"] %></td>
  <td><%= n["age"] %></td>
  <td><%= n["team"] %></td>
  <td><%= n["position"] %></td>
</tr>
<% end %>
</table>
```

以下のようなWebページが表示されるようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/9e2bafa1-e11f-37c2-7286-f560b4b3c113.png)

SQLが分かる方は、DB内のデータを直接いじって、表示内容が変わることをお楽しみいただいてもOKです

なお、`datas` の作成部分以外は、前回のマップリストと全く同じコードです（つまり、Elixir内部のデータ構造が全く同じ、なので、それを処理する側も全く同じ書き方で良い、ということを意味しています）

```elixir:前回マップリスト版のindex.html.heex
<%
datas = [
  %{"name" => "enぺだーし", "age" => 54, "team" => "有限会社デライトシステムズ", "position" => "代表取締役、性能探求者"}, 
  %{"name" => "ざっきー", "age" => 50, "team" => "公立大学法人 北九州市立大学", "position" => "准教授、カーネルハッカー"}, 
  %{"name" => "たくと", "age" => 40, "team" => "カラビナテクノロジー株式会社", "position" => "リードエンジニア"}, 
  %{"name" => "piacere", "age" => 48, "team" => "株式会社DigiDockConsulting", "position" => "常務取締役CTO、技術顧問、重力プログラマ"}
]
%>
<table>
<%= for n <- datas do %>
<tr>
    <td><%= n["name"] %></td>
    <td><%= n["age"] %></td>
    <td><%= n["team"] %></td>
    <td><%= n["position"] %></td>
</tr>
<% end %>
</table>
```

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

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

- Windows 10
  - 実機＋Elixir 1.8.1
    - Phoenix 1.4.2
  - 実機＋Elixir 1.6.x
    - Phoenix 1.3.x
  - Docker＋Elixir 1.6.x
    - Phoenix 1.3.x

# 終わり

今回で、DBデータをWebで表示できるようになりました

関数型言語によるWeb+DB開発が、こんなカンタンに出来ちゃうんだ … と感じていただけたら幸いです

データ元がDBに変わっても、画面側のコードが変わらなかったことに着目すると、関数型言語の威力がじょじょに見えてきます

[次回は、**Webに外部APIデータ表示** を行い、やはり画面側は、一切手直しがいらないことを更に実感していただきます](https://qiita.com/piacere_ex/items/4c212615a4eb699dd109)