LoginSignup
12
1

はじめに

この記事は 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を追加します

mix.exs
  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の設定を以下のように変更します

config/config.exs
# 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に変更します

lib/spotter_web/endpoint.ex
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番号の取得方法が変わります

lib/spotter.ex
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

アプリケーション設定ファイルを差し替えます

mix.exs
  def application do
    [
-      mod: {Spotter.Application, []},
+      mod: {Spotter, []},
      extra_applications: [:logger, :runtime_tools]
    ]
  end

iOS, Android開発でのDB設定

iOSとAndroidで開発するときはprod環境でビルドされるので
Dev環境の設定は無効化されており、DBとコネクションを貼るときにエラーになってアプリが落ちてしまいます
なのでProd環境の設定ファイルに以下を追加します

config/prod.exs
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

問題なく起動できました

スクリーンショット 2023-12-18 23.40.11.png

最後に

今回は DBをPostgresql、WebサーバーをBanditにしてアプリを作成してみました
次は認証機能の実装とセッション保持について解説します

本記事は以上になりますありがとうごうざいました

12
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
1