ゼロからElixir+Phoenixに入門する(1)
技術ブログからのお引越し(2020/1/23投稿)です。
こんにちは、空のもりわきです。
今回、社内の検証用プロトタイプを作る機会がありまして、ElixirとPhoenixで開発を行ってみました。
ElixirはRailsのコミッターであるJose Valim氏によって開発された関数型言語であり、Rubyライクに書くことができます。
Webアプリ用のフレームワークであるPhoenixもまたRailsのように書くことができるため、RubyやRailsを利用しているエンジニアならとっつきやすいのではないかとと思います。
Elixirを選択したモチベーションは、速い、軽い、友人の薦めなどありましたが、プロダクト開発の選択肢になりうるかを検証する意図もありました。
プロトタイプのゴール
社内で利用するアプリケーション機能として以下を目指します。
1. 商品情報を登録できる管理画面を作る
2. ユーザ登録を行い、emailでログインする
3. 認証したユーザだけ商品情報の登録編集が可能になる
4. 登録した商品情報を返却するAPIを用意する
環境構築
今回はmacに構築を行うため、brewを利用します。
elixirをインストールすることでmixコマンドが使えるようになります。
このmixはbundlerやyarnのようなパッケージ管理システムで、elixirパッケージのインストールやプロジェクトの管理を行うことができるようになります。
$ brew install elixir
$ elixir -v
Elixir 1.9.4 (compiled with Erlang/OTP 22)
$ mix archive.install hex phx_new 1.4.11
DBはMySQLを利用したかったため、databaseオプションを指定してphoenixのプロジェクトを作成します。
$ mix phx.new phoenix_admin --database mysql
ちなみにdatabaseオプションなしの場合はPostgreSQLがデフォルトで選択されます。
また、APIのみで構築する場合はno-htmlとno-webpackを指定することで作成できます。
$ mix phx.new phoenix_admin --database mysql --no-html --no-webpack
Accountコンテキストの作成
プロジェクトディレクトリに移動し、usersテーブルを作成します。
$ mix phx.gen.html Accounts User users name:string email:string:unique password:string
phx.gen.html により、controller, view, template, model, contextが1セットで作成されます(構成は以下)。
lib/
phoenix_admin/
accounts.ex # コンテキスト
accounts/
user.ex # モデル
phoenix_admin_web/
channels/
controller/
template/
views/
コンテキストはDDDにおいて「境界づけられたコンテキスト」と表現されます。
例えば、同じuserモデルを利用するにしても、認証のための処理、ユーザ管理のための処理、ユーザが持っている権限の処理などに分かれます。
これらのメソッドをすべてuserモデルの中で定義してしまうと一気にモデルが大きくなってしまいます。
これらを利用する側から見たグループ=コンテキストとして切り出してあげることで責務の分離が可能になります。
(小さなアプリの場合はまとめてもよいと思います。大きくなったら適切な名前をつけて分けてあげましょう。)
マイグレーション
ectoを利用してマイグレーションを行いますが、先にconfig/dev.exsを開いてDBの接続設定を行っておきます。
config :phoenix_admin, PhoenixAdmin.Repo,
username: "username",
password: "password",
database: "phoenix_admin_dev",
hostname: "localhost",
show_sensitive_data_on_connection_error: true,
pool_size: 10
設定ができれば、ecto.createでdatabaseを作成し、ecto.migrateでテーブルを作成します。
$ mix ecto.create
$ mix ecto.migrate
ルーティングの追加
lib/phoenix_admin_web/router.ex を編集します。
resources を追加することで CRUDに対応したエンドポイントが自動的に生成されます。このあたりはRailsと同じですが、resource(単数形)に対応する記述は無いようなので自前で書いてあげる必要があります。
scope "/", PhoenixAdminWeb do
pipe_through :browser
get "/", PageController, :index
resources "/users", UserController # 追加
end
phx.routes でルーティングが設定されているか確認します。
$ mix phx.routes
page_path GET / PhoenixAdminWeb.PageController :index
user_path GET /users PhoenixAdminWeb.UserController :index
user_path GET /users/:id/edit PhoenixAdminWeb.UserController :edit
user_path GET /users/new PhoenixAdminWeb.UserController :new
user_path GET /users/:id PhoenixAdminWeb.UserController :show
user_path POST /users PhoenixAdminWeb.UserController :create
user_path PATCH /users/:id PhoenixAdminWeb.UserController :update
PUT /users/:id PhoenixAdminWeb.UserController :update
user_path DELETE /users/:id PhoenixAdminWeb.UserController :delete
/users に対するリソースが生成されていますね!
起動
それではサーバを起動してみましょう。以下のコマンドでアプリケーションサーバを起動し、http://localhost:4000 にアクセスすることで画面を見ることができます。
$ mix phx.server
/users にアクセスするとユーザの一覧・登録・編集・削除が可能になりました!
ただし、このままではパスワードのHTMLタグが input type=”text” になっているので、template/user/form.htlm.eexを編集して password_input にしておきましょう。
<%= password_input f, :password %>
さらに、このままではパスワードが平文で保存されてしまいますので、hash化をしてあげる必要があります。
次回はguardianとargon2のパッケージを利用してemail+passwordでの認証処理とhash化を実装していきたいと思います。
この記事が参加している募集
この記事が気に入ったらサポートをしてみませんか?