Help us understand the problem. What is going on with this article?

[Elixir] PhoenixでJSONを返すWeb APIを作る

More than 5 years have passed since last update.

※ Phoenix 1.0.3

やること

  1. mix phoenix.gen.htmlする
  2. RouterにAPIリクエストを受けるためのpipelineを設定する
  3. ControllerでContent Negotiationを指定する
  4. ViewにJSONを返すよう記述する

1. 事前準備

以下を実行

mix phoenix.gen.html Note notes title:string description:text

mix phoenix.gen.jsonというタスクもあり、こちらはすぐにAPIを用意したいだけなら十分なコードが生成される。ただし管理に便利なWebUIは自動生成されないため、今回はmix phoenix.gen.htmlの方を使う。

2. Router

この辺はrouter.exにコメント書きされているのでなんとなくわかる。

web/router.ex
defmodule Demo.Router do
  use Demo.Web, :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 "/", Smaug do
    pipe_through :browser

    get "/", PageController, :index
    resources "/notes", NoteController
  end

  scope "/api", Smaug do
    pipe_through :api

    resources "/notes", NoteController, only: [:index, :show]
  end
end

plug :accepts, ["json"]を指定することで、Accept: application/jsonのあるHTTP Requestのみを許可してくれる。

また、resources/3でAPIとして公開するメソッドを制限できる。

3. Controller

生成されたControllerには、Templateのファイル名がStringでベタ書きされている。これだとAccept: application/jsonを指定したHTTP Requestを飛ばしてもContent Negotiationが行われない。

そこで、以下のようにAtomで指定する。

web/controllers/note_controller.ex
#(該当箇所のみ抜粋)
def index(conn, _params) do
  notes = Repo.all(Note)
  # render(conn, "index.html", notes: notes)
  render(conn, :index, notes: notes)
end

4. View

mixが生成したViewだとJSONへのencodingが行われず、poisonがエラーを出す。そのため以下のようにViewを修正する。

web/views/note_view.ex
defmodule Demo.NoteView do
  use Demo.Web, :view

  def render("index.json", %{notes: notes}) do
    %{data: render_many(notes, Demo.NoteView, "note.json")}
  end

  def render("show.json", %{story: story}) do
    %{data: render_one(note, Demo.NoteView, "note.json")}
  end

  def render("note.json", %{note: note}) do
    %{id: note.id,
      title: note.title,
      description: note.description}
  end
end

確認

curl 'http://localhost:4000/api/notes' -v -X GET -H 'Accept: application/json'
FL4TLiN3
Freelance Technology Handyman. Server and Front-End Programmer / Producer / Game Designer / Web Designer.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away