Skip to content

API利用法

ElixirでのAPIプロジェクトの作成

Section titled “ElixirでのAPIプロジェクトの作成”

ElixirPhoenixフレームワークを使用して、API専用のプロジェクトを作成する方法を紹介します。以下の手順で、データベースを使用する場合と使用しない場合のプロジェクトを作成できます。

データベースに接続してデータの永続化を伴うAPIを作成する場合、PhoenixプロジェクトはEctoをデフォルトで含みます。

  1. プロジェクトの作成

    • コマンド: mix phx.new my_api --no-html --no-webpack
    • 説明: HTMLやフロントエンドのビルドツールを含めず、バックエンドAPIに特化した構造を作成します。EctoPostgreSQLへの接続設定も含まれます。
  2. リソースの生成とデータベース操作

    • mix ecto.create: config/dev.exsの設定に基づいて、データベースを作成します。
    • mix phx.gen.json Accounts User users name:string: APIエンドポイントの作成を自動化します。Accountsというコンテキスト、Userというモデル、およびusersテーブルのマイグレーションファイルを生成します。
    • mix ecto.migrate: データベースマイグレーションを実行し、usersテーブルを作成します。

フォルダ構成(データベースあり)

Section titled “フォルダ構成(データベースあり)”
my_api/
├── config/
├── lib/
│ ├── my_api/
│ │ ├── accounts/
│ │ │ ├── user.ex # Userモデル
│ │ │ └── accounts.ex # コンテキストモジュール
│ │ └── repo.ex # データベースリポジトリ
│ └── my_api_web/
│ ├── controllers/
│ │ └── user_controller.ex # APIコントローラー
│ └── router.ex # ルーター
├── priv/
│ └── repo/
│ └── migrations/ # マイグレーションファイル
└── ...

データベースを使用しない、純粋なAPI(例:外部APIのプロキシやインメモリデータのみを扱う場合)を作成するには、プロジェクト生成時に--no-ectoフラグを追加します。

  1. プロジェクトの作成

    • コマンド: mix phx.new my_api --no-html --no-webpack --no-ecto
    • 説明: Ecto関連の依存関係や設定ファイルを一切含みません。
  2. APIエンドポイントの手動作成

    • lib/my_api_web/controllers/api_controller.ex: APIエンドポイントのロジックを記述します。
    • lib/my_api_web/router.ex: そのコントローラーへのルーティングを設定します。

フォルダ構成(データベースなし)

Section titled “フォルダ構成(データベースなし)”
my_api/
├── config/
├── lib/
│ └── my_api_web/
│ ├── controllers/
│ │ └── api_controller.ex # 手動で作成したコントローラー
│ └── router.ex # ルーター
├── priv/
└── ...
特徴データベースありAPIモードデータベースなしAPIモード
主な用途データの永続化が必要なAPI(例:ユーザー管理、ブログ投稿)データベースを必要としないAPI(例:外部APIのプロキシ、計算サービス)
プロジェクト作成mix phx.new --no-html --no-webpackmix phx.new --no-html --no-webpack --no-ecto
データ永続化Ectoによるデータベース接続❌ データベース接続なし
リソース作成phx.gen.jsonジェネレーターが利用可能❌ ジェネレーターは利用不可、手動で作成
利点複雑なデータモデルを効率的に管理できる不要な依存関係がなく、軽量でシンプル
考慮点開発環境のセットアップ(Postgresなど)が必要すべてのAPIエンドポイントを手動で定義する必要がある

どちらのモードを選択するかは、APIの目的によって決まります。データの読み書きが必要な場合はデータベースあり、外部サービスとの連携や単純な処理に特化する場合はデータベースなしが適しています。

Phoenixフレームワークでは、Webリクエストの処理がEndpointRouterという2つの主要なコンポーネントによって管理されます。これらは、リクエストの「入り口」と「交通整理役」として機能し、コードの役割を明確に分離します。

  1. Endpoint: アプリケーションの玄関口 🚪

    • Endpointは、Webリクエストがアプリケーションに到達する最初のポイントです。アプリケーションのHTTPサーバーとして機能し、ネットワーク接続の受付、初期設定、そしてすべてのリクエストをルーターに渡す役割を担います。

    • 主な役割: 接続の受付、SSL証明書の管理、リクエストの基本的なロギング、そしてPlugパイプラインの開始点。

    • 設定例 (config/config.exs): ポート番号やSSL設定が定義されます。

    config/config.exs
    config :my_app, MyAppWeb.Endpoint,
    http: [port: 4000],
    url: [host: "localhost"],
    plug: MyAppWeb.Router
  2. Router: リクエストの交通整理役 🚦

    • Routerは、Endpointが受け取ったリクエストを、URLに基づいて適切なコントローラーや処理ロジックに振り分ける役割を担います。

    • 主な役割: URLHTTPメソッド(GET, POSTなど)を対応するコントローラーの関数にマッピングすること。

    • 設定例 (lib/my_app_web/router.ex):

    lib/my_app_web/router.ex
    defmodule MyAppWeb.Router do
    use Phoenix.Router
    import Plug.Conn
    pipeline :api do
    plug :accepts, ["json"]
    plug Plug.Parsers, parsers: [:json]
    end
    scope "/api", MyAppWeb do
    pipe_through :api
    get "/users", UserController, :index
    end
    end

WebSocket通信:リアルタイムな連携 💬

Section titled “WebSocket通信:リアルタイムな連携 💬”

Phoenixは、Phoenix Channelsという抽象化を通じて、WebSocket通信を簡単に実装できます。これにより、リアルタイムな双方向通信(例:チャット、ライブ更新)が可能になります。これは、従来のREST APIだけでは実現が難しい、Elixirの強みが特に活かされる部分です。

  • Channelの定義: バックエンドで、特定のトピック(例: room:lobby)を購読するためのChannelモジュールを定義します。このモジュールは、クライアントからのメッセージを受け取り、処理し、ブロードキャストするロジックを保持します。

  • Socketの定義: lib/my_app_web/endpoint.exファイルで、WebSocket接続の入り口となるSocketを定義します。これは、クライアントが接続すべきエンドポイントになります。

  • Reactクライアントでの接続: Reactアプリケーションでは、phoenix.jsライブラリを使用してバックエンドに接続します。

バックエンド (Elixir)

まず、WebSocketの入り口となるソケットをEndpointに定義します。

lib/my_app_web/endpoint.ex
defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app
# ... 省略
socket "/socket", MyAppWeb.UserSocket,
websocket: true,
longpoll: false
# ... 省略
end

次に、メッセージを処理するChannelを定義します。

lib/my_app_web/channels/room_channel.ex
defmodule MyAppWeb.RoomChannel do
use Phoenix.Channel
# クライアントがトピックに参加する際に呼び出される
def join("room:" <> _room_name, _params, socket) do
{:ok, socket}
end
# クライアントからのメッセージを受信(`"new_msg"`イベント)
def handle_in("new_msg", %{"body" => body}, socket) do
# 受け取ったメッセージを同じトピックのすべてのクライアントにブロードキャスト
broadcast!(socket, "new_msg", %{body: body, sender: "Server"})
{:noreply, socket}
end
end

フロントエンド (React)

phoenix.jsライブラリを使用して、バックエンドのWebSocketエンドポイントに接続し、チャネルを購読します。

import { Socket } from "phoenix";
// WebSocketエンドポイントに接続
let socket = new Socket("ws://localhost:4000/socket", {});
socket.connect();
// 特定のトピックを購読するチャネルを作成
let channel = socket.channel("room:lobby", {});
// チャネルへの接続を試行
channel.join()
.receive("ok", resp => console.log("Joined successfully", resp))
.receive("error", resp => console.log("Unable to join", resp));
// バックエンドからメッセージを受信
channel.on("new_msg", payload => {
console.log("Received a new message:", payload.body);
});
// ボタンクリックなどでバックエンドにメッセージを送信
document.getElementById("send-btn").onclick = () => {
let message = "Hello from React!";
channel.push("new_msg", {body: message});
};

この連携により、リアルタイムなチャットアプリや、バックエンドでのデータ変更を即座にフロントエンドに反映するライブ更新機能などを、効率的に構築できます。

これらの例は、ElixirPhoenixAPI開発とリアルタイム通信の両方にいかに強力なツールであるかを示しています。ご質問があれば、いつでもお尋ねください。

ElixirPhoenixフレームワークで、ReactVue.jsのような**SPA(Single Page Application)**と連携する場合、主に2つの方法があります。これらの方法は、それぞれ異なるユースケースと利点を持っています。

  1. APIサーバーとして疎通する(REST API & WebSocket

    • これは最も一般的で柔軟なアプローチです。PhoenixAPIサーバーとして機能し、SPAFetch APIAxiosphoenix.jsライブラリなどを使ってバックエンドと通信します。

    • 特徴

      • 完全な分離: フロントエンドとバックエンドが完全に独立しています。これにより、それぞれを別のチームで開発したり、異なる技術スタックで構築したりすることが可能です。
      • 汎用性: モバイルアプリや他のクライアント(IoTデバイスなど)とも同じAPIを共有できます。
      • 認証: JWTJSON Web Token)やセッションベースの認証など、標準的なAPI認証手法を使用します。
      • リアルタイム通信: Phoenix Channelsを通じてWebSocket通信を実装し、チャットやリアルタイム通知などの機能を簡単に構築できます。
    • 実装例

      • Phoenixプロジェクトの作成: API専用プロジェクトとして作成します。
      Terminal window
      mix phx.new my_api --no-html --no-webpack --no-live
      • APIエンドポイント: REST APIとして、JSON形式でデータをやり取りします。
      lib/my_app_web/router.ex
      scope "/api", MyAppWeb do
      pipe_through :api
      get "/posts", PostController, :index
      post "/posts", PostController, :create
      end
      • Reactからのデータ取得: React側では、useEffectフックなどを使ってAPIを呼び出します。
      import React, { useEffect, useState } from 'react';
      function PostsList() {
      const [posts, setPosts] = useState([]);
      useEffect(() => {
      fetch('/api/posts')
      .then(response => response.json())
      .then(data => setPosts(data));
      }, []);
      return (
      <div>
      {posts.map(post => (
      <div key={post.id}>{post.title}</div>
      ))}
      </div>
      );
      }
  2. Phoenix LiveViewで疎通する

    • LiveViewは、ElixirPhoenixの最も革新的な機能の一つです。HTMLをサーバー側でレンダリングし、WebSocketを通じてHTMLの差分だけをクライアントに送信することで、JavaScriptをほとんど書かずにリッチなUIを実現します。

    • 特徴

      • サーバーサイドレンダリング: サーバー側でレンダリングを行うため、初期表示が高速です。
      • 開発体験: サーバー側のElixirコードだけでUIのロジックを完結できるため、JavaScriptElixirの間でコンテキストスイッチが不要になり、開発効率が大幅に向上します。
      • リアルタイム性: ユーザーアクションは即座にサーバーに送信され、UIの更新がWebSocket経由でリアルタイムに反映されます。
      • ステート管理: アプリケーションの状態(State)はすべてサーバーで管理されるため、フロントエンドの複雑なステート管理ライブラリ(Redux, Zustandなど)が不要になります。
    • 実装例

      • プロジェクトの作成: LiveViewを含めてプロジェクトを作成します。
      Terminal window
      mix phx.new my_app
      • LiveViewコンポーネント: ユーザーがクリックするとカウントが増えるシンプルなカウンターの例です。
      lib/my_app_web/live/counter_live.ex
      defmodule MyAppWeb.CounterLive do
      use MyAppWeb, :live_view
      @impl true
      def mount(_params, _session, socket) do
      {:ok, assign(socket, count: 0)}
      end
      @impl true
      def handle_event("increment", _params, socket) do
      {:noreply, update(socket, :count, &(&1 + 1))}
      end
      end
      • HTMLテンプレート: ボタンがクリックされると、phx-click属性がサーバーのhandle_event関数を呼び出します。
      <div>
      <p>Count is: <%= @count %></p>
      <button phx-click="increment">Increment</button>
      </div>

      LiveViewは、このHTMLテンプレートをサーバーでレンダリングし、WebSocketを通じて変更を効率的に同期します。これにより、クライアント側ではHTMLと少量のJavaScriptだけで、動的なUIが実現されます。

  • APIサーバーとして疎通:

    • おすすめのケース: React Nativeのようなモバイルアプリや、複数の異なるクライアントをサポートする必要がある場合。フロントエンドとバックエンドの技術を完全に分離したいチーム。
  • LiveView:

    • おすすめのケース: 開発チームがElixirに精通しており、フロントエンドの複雑なステート管理やビルドプロセスを避けたい場合。リアルタイム性が重要で、UIを迅速に構築する必要がある場合。

LiveViewは、SPAの複雑さをサーバー側で吸収することで、開発の生産性を劇的に向上させます。しかし、既存のReactプロジェクトと統合する場合はAPIアプローチが適しています。どちらの方法も、Elixirの並行処理の強みを活かし、スケーラブルなアプリケーションを構築できます。