search
LoginSignup
50

More than 5 years have passed since last update.

posted at

updated at

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

※ 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'

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
What you can do with signing up
50