はじめに
この記事は Elixirアドベントカレンダーのシリーズ4の17日目の記事です
このシリーズでは内部DBをSQlite3にしたスタンドアローン、Phoenix APIサーバーとクライアントElixirDesktopアプリと解説してきました
今回はクラサバ構成 DB共有でAPIレス開発に付いて解説します
アプリケーション構成
今回はWebアプリまた管理ダッシュボードとしてPhoenixサーバーを構築し、そこで使用しているDBにアクセスして読み書きを行う構成です
[Phoenix Dashboard App] -- [Postgres] -- [ElixirDesktop App]
メリデメ
メリット
- phx.gen.liveやauthで作成したコードをそのまま使える
- APIを作る必要がない
- umbrella構成の知見があると単一レポジトリでWeb,スマホの開発ができる
デメリット
- ElixirDesktopでCのライブラリ等nifを使用するライブラリが動かない
phx.gen.authで暗号化を行う BcryptElixirがこれに該当し、AI/MLのライブラリも多く該当します。 - ストアに通るのかよくわからない
スタンドアローンとAPIクラサバ構成のアプリはストアに多くあるので問題ないが、DBに直接通信するタイプのアプリがあまりきかないので大丈夫だとは思うが出してないのでわからない
デメリットに対してAPIを作る必要がないのメリットがでかすぎるので、無事審査に通るといいなと思います
プロジェクト作成
GooglePlaces APIとGoogleMapを使用した、スポット登録とGPSロガーを機能として持つSpotterというアプリを作っていきます
DBはpostgresqlなのでそのままで、webサーバーをcowboyからbanditに変更してみましょう
mix phx.new spotter --adapter bandit
プロジェクトの作成が完了したら、ログに従ってプロジェクトフォルダに移動してDBを作成しましょう
cd spotter
mix ecto.create
ライブラリの追加
SQLite3は使わないのでdektop関連とGoogleのAPIを使うのでReqを追加します
defp deps do
[
...
{:desktop, "~> 1.5"},
{:wx, "~> 1.1", hex: :bridge, targets: [:android, :ios]},
{:req, "~> 0.3"}
]
end
追加したら以下のコマンドを実行します
mix deps.get
config修正
configファイルをElixirDesktopに合わせて変更します
Endpointの設定を以下のように変更します
# Configures the endpoint
config :spotter, SpotterWeb.Endpoint,
- url: [host: "localhost"],
+ http: [ip: {127, 0, 0, 1}, port: 10_000 + :rand.uniform(45_000)],
adapter: Bandit.PhoenixAdapter,
render_errors: [
formats: [html: SpotterWeb.ErrorHTML, json: SpotterWeb.ErrorJSON],
layout: false
],
pubsub_server: Spotter.PubSub,
- live_view: [signing_salt: "2TfGmFjF"]
+ live_view: [signing_salt: "2TfGmFjF"],
+ secret_key_base: :crypto.strong_rand_bytes(32),
+ server: true
portの設定はiOSのバックグラウンドモードからの復帰時に必要です
server: trueとすることで、スマホ内で起動したPhoenixアプリケーションをWebViewから閲覧ができます
config/runtime.exsがあるとエラーになるのでruntime_disable.exsにリネームします
Ednpoint
Banditを使う場合は use のモジュールはそのままで、
セッション管理をcookieから EralangビルドインインメモリDBのetsに変更します
defmodule SpotterWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :spotter
@session_options [
- store: :cookie,
+ store: :ets,
key: "_spotter_key",
+ table: :session
- signing_salt: "CQS/fw0h",
- same_site: "Lax"
]
...
end
アプリケーション起動時の設定
アプリケーション起動時に実行される、プロセス監視を行うsuperviserの設定を行います
SQLiteは使わないので、DB initiaizeは行わないのと port番号の取得方法が変わります
defmodule Spotter do
use Application
@moduledoc """
dekstop logic
"""
def config_dir() do
Path.join([Desktop.OS.home(), ".config", "spotter"])
end
@app Mix.Project.config()[:app]
def start(:normal, []) do
# configフォルダを掘る
File.mkdir_p!(config_dir())
# session用のETSを起動
:session = :ets.new(:session, [:named_table, :public, read_concurrency: true])
children = [
Spotter.Repo,
{Phoenix.PubSub, name: Spotter.PubSub},
SpotterWeb.Endpoint
]
opts = [strategy: :one_for_one, name: Spotter.Supervisor]
# メインのsuperviser起動
{:ok, sup} = Supervisor.start_link(children, opts)
# phoenixサーバーが起動中のポート番号を取得
{:ok, {_ip, port}} = Bandit.PhoenixAdapter.server_info(SpotterWeb.Endpoint, :http)
# メインのsuperviserの配下にElixirDesktopのsuperviserを追加
{:ok, _} =
Supervisor.start_child(sup, {
Desktop.Window,
[
app: @app,
id: SpotterWindow,
title: "Spotter",
size: {400, 800},
url: "http://localhost:#{port}"
]
})
end
def config_change(changed, _new, removed) do
SpotterWeb.Endpoint.config_change(changed, removed)
:ok
end
end
アプリケーション設定ファイルを差し替えます
def application do
[
- mod: {Spotter.Application, []},
+ mod: {Spotter, []},
extra_applications: [:logger, :runtime_tools]
]
end
iOS, Android開発でのDB設定
iOSとAndroidで開発するときはprod環境でビルドされるので
Dev環境の設定は無効化されており、DBとコネクションを貼るときにエラーになってアプリが落ちてしまいます
なのでProd環境の設定ファイルに以下を追加します
config :spotter, Spotter.Repo,
username: "postgres",
password: "postgres",
database: "spotter_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
if Mix.target() == :ios do
config :spotter, Spotter.Repo, hostname: "127.0.0.1"
end
if Mix.target() == :android do
config :spotter, Spotter.Repo, hostname: "10.0.2.2"
end
問題なく起動できました
最後に
今回は DBをPostgresql、WebサーバーをBanditにしてアプリを作成してみました
次は認証機能の実装とセッション保持について解説します
本記事は以上になりますありがとうごうざいました