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

昨日は、@takasehideki さんの「ElixirでIoT#2:いろいろ分かるベンチマークを整備してみる」でした


fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます:bow:

この連載の、前回までの記事は、以下になります
 |> Excelから関数型言語マスター1回目:行の「並べ替え」と「絞り込み」
 |> Excelから関数型言語マスター2回目:「列の抽出」と「Web表示」

今回は、Web上にDBデータを表示します


:stars::stars::stars::stars::stars: お知らせ :stars::stars::stars::stars::stars:
「fukuoka.ex#11:DB/データサイエンスにコネクトするElixir」を6/22(金)19時に開催します
スペシャルゲストとして、Erlang+Elixir界で、世界的にも有名な「力武 健次さん」が初参戦です:laughing:

image.png

DBのインストール

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

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

image.png

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

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

①PostgreSQLのインストール

image.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/

②MySQLのインストール

image.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

DBPhoenixのPJ作成、DB作成、起動

Phoenixプロジェクトを作成します

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

※PostgreSQLの場合
mix phx.new sample_db --no-brunch
※MySQLの場合
mix phx.new sample_db --no-brunch --database=mysql

パスワードを、PostgreSQLは「postgres」、MySQLは未設定(空文字列)で設定していない場合は、下記の「password」項目の修正が必要です

config/dev.exs ※PostgreSQLの場合

# Configure your database
config :sample_db, SampleDb.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  database: "sample_db_dev",
  hostname: "localhost",
  pool_size: 10
config/dev.exs MySQLの場合

# Configure your database
config :sample_db, SampleDb.Repo,
  adapter: Ecto.Adapters.MySQL,
  username: "root",
  password: "password",
  database: "sample_db_dev",
  hostname: "localhost",
  pool_size: 10

DBを作成します ※作成しないとiex内でエラー連発となるのでお忘れなく

mix ecto.create

Phoenixサーバーを起動します

iex -S mix phx.server

ブラウザで「localhost:4000」にアクセスすると、Phoenixで作られたWebページが見れます

image.png

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

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

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

※PostgreSQLの場合
psql

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内で入力します

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

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

insert into members values( 1, 'enぺだーし', 49, '有限会社デライトシステムズ', '代表取締役, 性能探求者' );
insert into members values( 2, 'ざっきー', 45, '公立大学法人 北九州市立大学', '准教授, カーネルハッカー' );
insert into members values( 3, 'つちろー', 34, 'カラビナテクノロジー株式会社', 'リードエンジニア, アプリマイスター' );
insert into members values( 4, 'ゆじかわ', 30, 'カラビナテクノロジー株式会社', 'リードエンジニア, グロースハッカー' );
insert into members values( 5, 'piacere', 43, '株式会社TechJIN', 'CTO, 福岡Elixirプログラマ, 重力プログラマ, 技術顧問' );

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

※PostgreSQLの場合
postgres=# \q
※MySQLの場合
mysql> exit

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

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

なお、コード中の「SampleDb.Repo」の部分は、作成するPJ名によって変わるため、「SampleDb」の部分をPJ名と同じにしてください

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ページの元となるファイルを書き換えます

lib/sample_db_web/templates/page/index.html.eex
<%
result = Db.query( "select * from members" )
data = result |> Db.columns_rows
%>
<table border="1">
<%= for record <- data do %>
<tr>
    <td><%= record[ "name" ] %></td>
    <td><%= record[ "age" ] %></td>
    <td><%= record[ "team" ] %></td>
    <td><%= record[ "position" ] %></td>
</tr>
<% end %>
</table>

以下のようなWebページが表示されるようになります

image.png

なお、dataの作成以外は、前回のマップリストと全く同じコードです(つまり、データ構造も全く同じ、ということです)

前回マップリスト版のindex.html.eex
<%
data = 
[
  %{ "name" => "enぺだーし", "age" => 49, "team" => "有限会社デライトシステムズ", "position" => "代表取締役, 性能探求者" }, 
  %{ "name" => "ざっきー", "age" => 45, "team" => "公立大学法人 北九州市立大学", "position" => "准教授, カーネルハッカー" }, 
  %{ "name" => "つちろー", "age" => 34, "team" => "カラビナテクノロジー株式会社", "position" => "リードエンジニア, アプリマイスター" }, 
  %{ "name" => "ゆじかわ", "age" => 30, "team" => "カラビナテクノロジー株式会社", "position" => "リードエンジニア, グロースハッカー" }, 
  %{ "name" => "piacere", "age" => 43, "team" => "株式会社TechJIN", "position" => "CTO, 福岡Elixirプログラマ, 重力プログラマ, 技術顧問" }
]
%>
<table border="1">
<%= for record <- data do %>
<tr>
  <td><%= record[ "name" ] %></td>
  <td><%= record[ "age" ] %></td>
  <td><%= record[ "team" ] %></td>
  <td><%= record[ "position" ] %></td>
</tr>
<% end %>
</table>

終わり

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

関数型言語によるWeb+DBアプリ開発が、こんな位でできちゃうんだ…と感じていただけたら幸いです

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

次回は、別のデータ元を導入する、「Webに外部APIデータ表示」を行い、やはり画面側は、一切手直しがいらないことを更に実感していただきます

明日は、@wataridori999 さんの「ElixirでSI開発入門 #3 主キーがid 出ない既存DBへの接続」です

p.s.「いいね」よろしくお願いします

ページ左上の image.pngimage.png のクリックを、どうぞよろしくお願いします:bow:
ここの数字が増えると、書き手としては「ウケている」という感覚が得られ、連載を更に進化させていくモチベーションになりますので、もっとElixirネタを見たいというあなた、私達と一緒に盛り上げてください!:tada:

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.