19
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Phoenix 1.4正式版② DB+API編

Last updated at Posted at 2018-11-10

fukuoka.ex代表のpiacereです
ご覧いただいて、ありがとうございます:bow:

前回、インストールした、ElixirのWebフレームワーク「Phoenix」の新バージョン1.4で、DBと紐付くAPIを作ってみます

なお、Phoenix 1.4正式版のEctoは、メジャーバージョンアップした3.0になっているので、その試しにもなっています

この連載の、前回までの記事は、以下になります
 |> Phoenix 1.4正式版① インストール編

あと、参考までに、rc版を試したときのコラムは、以下になります
 |> Phoenix 1.4rcを試す① アップデート紹介編
 |> Phoenix 1.4rcを試す② インストール編(不具合時の復旧もあるよ)
 |> Phoenix 1.4rcを試す③ ローカルSSL開発編(Gigalixirのオマケ付)
 |> Phoenix 1.4rcを試す④ webpack編

内容が、面白かったり、気に入ったら、「いいね」よろしくお願いします :wink:

事前準備:PostgreSQLをインストール

今回、DBを利用するため、PostgreSQLをあらかじめインストールする必要があります

以前、書いたコラムをご参考ください

DBを使うPhoenixのPJ作成、DB作成、起動

DB利用有のPhoenix PJを作成します

なお、PJ名に「Web」という文字列を含むと、フォルダ作成やモジュール命名の都合から、不具合が出るため、入れないよう気を付けてください(エラーメッセージから判断付けるのは、かなり困難なので、ご注意を)

mix phx.new phx14_db --no-webpack
 …(ファイル作成ログが続く)…
Fetch and install dependencies? [Yn] (←y、Enterを入力)

実際にインストールされたCowboyやEctoのバージョンが、幾つなのか、ライブラリバージョンを確認するため、mix.lockを見てみましょう

mix.lock
%{
  "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [], [], "hexpm"},
  "cowboy": {:hex, :cowboy, "2.5.0", "4ef3ae066ee10fe01ea3272edc8f024347a0d3eb95f6fbb9aed556dacbfc1337", [], [{:cowlib, "~> 2.6.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.6.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
  "cowlib": {:hex, :cowlib, "2.6.0", "8aa629f81a0fc189f261dc98a42243fa842625feea3c7ec56c48f4ccdb55490f", [], [], "hexpm"},
  "db_connection": {:hex, :db_connection, "2.0.1", "09454c6c6e8e4295f400b72580b19f0ac68fda2602e209533285206cb99bee6b", [], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
  "decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [], [], "hexpm"},
  "ecto": {:hex, :ecto, "3.0.1", "a26605ee7b243a754e6609d1c23da27bcb22823659b07bf03f9020da92a8e4f4", [], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
  "ecto_sql": {:hex, :ecto_sql, "3.0.0", "8d1883376bee02a0e76b5ef797e39d04333c34b9935d0b4785dbf3cbdb571e2a", [], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.2.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
  "file_system": {:hex, :file_system, "0.2.6", "fd4dc3af89b9ab1dc8ccbcc214a0e60c41f34be251d9307920748a14bf41f1d3", [], [], "hexpm"},
  "gettext": {:hex, :gettext, "0.16.0", "4a7e90408cef5f1bf57c5a39e2db8c372a906031cc9b1466e963101cb927dafc", [], [], "hexpm"},
  "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
  "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [], [], "hexpm"},
  "phoenix": {:hex, :phoenix, "1.4.0", "56fe9a809e0e735f3e3b9b31c1b749d4b436e466d8da627b8d82f90eaae714d2", [], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
  "phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
  "phoenix_html": {:hex, :phoenix_html, "2.12.0", "1fb3c2e48b4b66d75564d8d63df6d53655469216d6b553e7e14ced2b46f97622", [], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
  "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.0", "3bb31a9fbd40ffe8652e60c8660dffd72dd231efcdf49b744fb75b9ef7db5dd2", [], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
  "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.1", "6668d787e602981f24f17a5fbb69cc98f8ab085114ebfac6cc36e10a90c8e93c", [], [], "hexpm"},
  "plug": {:hex, :plug, "1.7.1", "8516d565fb84a6a8b2ca722e74e2cd25ca0fc9d64f364ec9dbec09d33eb78ccd", [], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}], "hexpm"},
  "plug_cowboy": {:hex, :plug_cowboy, "2.0.0", "ab0c92728f2ba43c544cce85f0f220d8d30fc0c90eaa1e6203683ab039655062", [], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
  "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [], [], "hexpm"},
  "postgrex": {:hex, :postgrex, "0.14.0", "f3d6ffea1ca8a156e0633900a5338a3d17b00435227726baed8982718232b694", [], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
  "ranch": {:hex, :ranch, "1.6.2", "6db93c78f411ee033dbb18ba8234c5574883acb9a75af0fb90a9b82ea46afa00", [], [], "hexpm"},
  "telemetry": {:hex, :telemetry, "0.2.0", "5b40caa3efe4deb30fb12d7cd8ed4f556f6d6bd15c374c2366772161311ce377", [], [], "hexpm"},
}

Cowboyが2.5、Ectoが3.0.1であることが確認できました

Telemetryもインストールされていますね:wink:

参考までに、mix.exsも見ておきましょう

mix.exs

  defp deps do
    [
      {:phoenix, "~> 1.4.0"},
      {:phoenix_pubsub, "~> 1.1"},
      {:phoenix_ecto, "~> 4.0"},
      {:ecto_sql, "~> 3.0"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.11"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"}
    ]
  end

CowboyやTelemetryの個別記載が無いことから、Phoenix 1.4かEctoの依存に含まれたことが確認できます(詳しくは、HexのDependenciesを追ってください)

PostgreSQLのパスワードが、「postgres」で無い場合は、下記の「password」項目の修正が必要です

config/dev.exs ※PostgreSQLの場合

# Configure your database
config :phx14_db, Phx14Db.Repo,
  username: "postgres",
  password: "postgres",
  database: "blog_dev",
  hostname: "localhost",
  pool_size: 10

おや?「adapter: Ecto.Adapters.Postgres,」の記載が無くなっていますね…これで動くのかしら?

まぁ、ひとまず、DBを作成します ※作成しないとiex内でエラー連発となるのでお忘れなく

cd phx14_db
mix ecto.create

作成できました(PostgreSQL側も、念のため確認しましたが、無事、作られていました)

Phoenixを起動します

iex -S mix phx.server

Phoenix起動の際、以下ログが出ていれば起動成功です

…
[info] Running BlogWeb.Endpoint with cowboy 2.5.0 at http://localhost:4000
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
iex> 

ブラウザで「http://localhost:4000」をアクセスすると、以下ページが表示されます

image.png

PhoenixでDBアクセスするAPIを作る

以下コマンドで、DBアクセスするAPIを作ります

Ctrl+cを2回押して、一度、Phoenixを停止してから、コマンドを入力します

mix phx.gen.json Api Post posts title:string body:text

以下ログと、実行後の作業指示が示されます

* creating lib/blog_web/controllers/post_controller.ex
* creating lib/blog_web/views/post_view.ex
* creating test/blog_web/controllers/post_controller_test.exs
* creating lib/blog_web/views/changeset_view.ex
* creating lib/blog_web/controllers/fallback_controller.ex
* creating lib/blog/api/post.ex
* creating priv/repo/migrations/20181110064453_create_posts.exs
* creating lib/blog/api/api.ex
* injecting lib/blog/api/api.ex
* creating test/blog/api/api_test.exs
* injecting test/blog/api/api_test.exs

Add the resource to your :api scope in lib/blog_web/router.ex:

    resources "/posts", PostController, except: [:new, :edit]

Remember to update your repository by running migrations:

    $ mix ecto.migrate

まず、ルーティングにAPI用エントリーとして、上記「resources "/posts", ~」を、「get "/", ~」直下に追記します

lib/phx14_db_web/router.ex
defmodule Phx14DbWeb.Router do
  use Phx14DbWeb, :router
  
  scope "/", Phx14DbWeb do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
    resources "/posts", PostController, except: [:new, :edit]
  end
  

マイグレートします

mix ecto.migrate

以下ログのように、テーブルが作成されます

[debug] QUERY OK source="schema_migrations" db=0.0ms
SELECT s0."version"::bigint FROM "schema_migrations" AS s0 FOR UPDATE []
[info] == Running 20181110064453 Phx14Db.Repo.Migrations.CreatePosts.change/0 forward
[info] create table posts
[info] == Migrated 20181110064453 in 0.0s

Phoenix 1.3+Ecto 2系のときと、ログが少し変わってました

では、Phoenixを起動してください

iex -S mix phx.server

APIでDBへのデータ投入、読み込み

では、APIでデータ投入してみましょう

APIを叩くために、REST APIクライアントが必要ですが、Firefoxの「RESTClient」、Chromeの「Postman」が便利です

Firefox「RESTClient」
https://addons.mozilla.org/ja/firefox/addon/restclient/

Chrome「Postman」
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop

ここでは、FirefoxのRESTClientをインストールして、使ってみます

まず、RESTClientの「Headers」メニューで、「Custom Header」を選択して、REST API用のヘッダー設定をします
image.png

次に、URLに「http://localhost:4000/posts」を入れ、「Method」を「POST」に変更し、「Body」に以下を入力します

{ "post": { "title": "t1", "body": "b1" } }

「SEND」ボタンをクリックすると、以下の通り、エラーになります
image.png

「Response」の中身を見てみると、CSRFトークンエラーが出ています
image.png

これは、リクエストにCSRFトークンが付与されていないことが原因ですが、ステートレスなAPIでCSRF対応するのは本筋から外れるので、いったんシンプルに、router.exに設定されているSCRF対策を解除します

lib/phx14_db_web/router.ex
defmodule Phx14DbWeb.Router do
  use Phx14DbWebWeb, :router

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

コンパイルします

iex> recompile

再度、「SEND」ボタンをクリックすると、今度は成功します
image.png

「Method」を「GET」に切り替え、「SEND」ボタンをクリックすると、投入したデータが返っていることが確認できます
image.png

終わり

Phoenix 1.4でも、1.3時と変わらず、DB+APIがサクっと作れました

次回は、GraphQLライブラリ「Absinthe」をPhoenix 1.4にて動かしてみようと思います

p.s.「いいね」よろしくお願いします

よろしければ、ページ左上の image.pngimage.png のクリックをお願いしますー:bow:

19
10
0

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
  3. You can use dark theme
What you can do with signing up
19
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?