Elixir + Phoenixを使用してアプリを作成しようとすると、そのリソースを処理するための「ブラウザー」リクエストと「api」リクエストの両方を処理できるようになります。
そのようなことをしなくてもそれを行うことは可能ですか?
scope "/", App do
pipe_through :browser
resources "/users", UserController
end
scope "/api", App.API as: :api do
pipe_through :api
resources "/users", UserController
end
これは、2つのコントローラーを作成する必要があることを意味します。これは、browserパイプラインでHTMLをレンダリングし、apiパイプラインでJSONをレンダリングすることを除いて、同じ動作をする可能性があります。
私は多分Rails respond_to do |format| ...
のようなものを考えていました
私はそれをお勧めしません(2つのコントローラーを用意し、両方のコントローラーによって呼び出される別のモジュールにロジックを移動することをお勧めします)が、それは可能です。コントローラーを共有することはできますが、正しい応答タイプ(html/json)が設定されていることを確認するには、別のパイプラインが必要です。
以下は同じコントローラーとビューを使用しますが、ルートに応じてjsonまたはhtmlをレンダリングします。 「/」はhtml、「/ api」はjsonです。
ルーター:
defmodule ScopeExample.Router do
use ScopeExample.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", ScopeExample do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
scope "/api", ScopeExample do
pipe_through :api # Use the default browser stack
get "/", PageController, :index
end
end
コントローラ:
defmodule ScopeExample.PageController do
use ScopeExample.Web, :controller
plug :action
def index(conn, params) do
render conn, :index
end
end
見る:
defmodule ScopeExample.PageView do
use ScopeExample.Web, :view
def render("index.json", _opts) do
%{foo: "bar"}
end
end
次のようなルーターを使用する場合は、ルーターを共有して、すべてを同じルートで処理することもできます。
defmodule ScopeExample.Router do
use ScopeExample.Web, :router
pipeline :browser do
plug :accepts, ["html", "json"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
end
scope "/", ScopeExample do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
end
次に、URLの最後に?format=json
を使用して形式を指定できます。ただし、APIとサイトに異なるURLを使用することをお勧めします。
Gazlerが言ったように、おそらく別々のパイプラインを使用するのが最善ですが、このようなことは、同じコントローラーアクションでパターンマッチングを使用して快適に行うことができます。
def show(conn, %{"format" => "html"} = params) do
# ...
end
def show(conn, %{"format" => "json"} = params) do
# ...
end
または、関数本体が同じで、acceptヘッダーに基づいてテンプレートのみをレンダリングする場合は、次の操作を実行できます。
def show(conn, params) do
# ...
render conn, :show
end
テンプレート名としてatomを渡すと、phoenixはacceptヘッダーをチェックし、.json
または.html
テンプレートをレンダリングします。