Феникс: Наличие JSON и HTML представления одного и того же ресурса - PullRequest
1 голос
/ 07 октября 2019

Я начинаю использовать Phoenix вне учебных пособий для небольшого варианта использования. Пока все отлично, но я немного удивлен следующим:

У меня есть ресурс «запись», к которому я хочу получить доступ в / api / записи в JSON и в / запись с шаблоном ив результате получается HTML.

В идеале представление Ecto должно быть уникальным, и даже часть контроллера также будет разделена?

Прямо сейчас мне нужно иметь 2 ресурса для записи API и записиHTML, или 2контроллеры и 1 ресурс.

Есть какой-нибудь пример? Я продолжаю находить одно или другое, но не что-то с: api pipe и: browser browser, используемыми для одного и того же ресурса.

Спасибо

1 Ответ

3 голосов
/ 07 октября 2019

Вы можете использовать штекер phoenix accepts и комбинацию двух разных видов / макетов

# router.ex
defmodule TestExWeb.Router do
  use TestExWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", TestExWeb do
    pipe_through :browser

    get "/recording", PageController, :index
  end

  scope "/api", TestExWeb do
    pipe_through :api

    get "/recording", PageController, :index
  end
end

Как видите, :browser использует :accepts ["html"], а :api использует :accepts ["json"]. Вы можете найти это в частной структуре вашего conn и использовать его в контроллере следующим образом:

defmodule TestExWeb.PageController do
  use TestExWeb, :controller

  def index(%{private: %{phoenix_format: format}} = conn, _params) do
    data = "Hello World"

    render(conn, "index.#{format}", data: data)
  end
end

Теперь вам просто нужно сказать Phoenix, как визуализировать ваш JSON, HTML уже позаботилсяof на page.html.eex в макетах, поэтому добавьте следующее к вашему page_view.ex

defmodule TestExWeb.PageView do
  use TestExWeb, :view

  def render("index.json", %{data: data}) do
    %{
      data: data
    }
  end
end

Два недостатка с этим решением:

  • Этот фрагмент кода необходим в каждом контроллере (Может быть, вы можете обойти это с помощью плагина после того, как «отправили» ответ)
  • Вы используете внутреннюю переменную phoenix
...