この辺りを参考にしました。
UUIDs as primary keys in Phoenix (with Ecto and Elixir)(medium)
How to customize id of Phoenix(stackoverflow)
プロジェクト作成
mix phx.new uuid_auto_sample
# 終わったら、
cd uuid_auto_sample
データベース作成
psqlは起動しておいてください。
mix ecto.create
plug_cowboy追加
idとは関係ありませんが、今私が使っているバージョンだと、このエラーが出るので対処しておきます。(qiitaの情報)
mix.exs
に、パッケージを追加
# 一部だけ載せています
defp deps do
[
{:phoenix, "~> 1.3.4"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.2"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.10"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"}, # <-- カンマ追加(よく忘れるので)
{:plug_cowboy, "~> 1.0"} # <-- これを追加
]
end
依存パッケージインストール
mix deps.get
動かしてみる
一旦、起動できるか確認しておきます。
mix phx.server
localhost:4000にアクセスしてWelcome to Phoenixというページが出ていれば良い。
テーブル定義
id, email, nameのフィールドを持つユーザーテーブルを作ります。
ここではidを含めません。
mix phx.gen.json Users User users email:string name:string
以下のようなメッセージが出ると思います。
Add the resource to your :api scope in lib/uuid_auto_sample_web/router.ex:
resources "/users", UserController, except: [:new, :edit]
Remember to update your repository by running migrations:
$ mix ecto.migrate
言われた通り、lib/uuid_auto_sample_web/router.ex
にリソースを追加します。mix ecto.migrate
はやらないでください。
# 一部だけ載せています
pipeline :api do
plug :accepts, ["json"]
end
scope "/", UuidAutoSampleWeb do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
# 以下の4行追加
scope "/api", UuidAutoSampleWeb do
pipe_through :api
resources "/users", UserController, except: [:new, :edit]
end
end
Ecto.UUIDを自動生成するようにスキーマ修正
lib/uuid_auto_sample/users/user.ex
に2行します。最初に紹介したmediumなどの記事だと、:id
の型を:binary_id
にしていますが、今はEcto.UUID
が使えるので、それにします。
中の仕組みがまだよくわかっていませんが、UUID4を自動生成してくれるようになります。おそらくどこかでEcto.UUID.generate
が呼ばれているんだとは思います。
# 一部だけ載せています
defmodule UuidAutoSample.Users.User do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, Ecto.UUID, autogenerate: true} # <-- これを追加
@derive {Phoenix.Param, key: :id} # <-- これも追加
schema "users" do
field :email, :string
field :name, :string
timestamps()
end
マイグレーションを修正
create table
で勝手にintのidが生成されないように(primary_key: falseのところ)、そして、自分で作ったuuidがprimary keyとして使われるように(行追加したところ)修正します。
defmodule UuidAutoSample.Repo.Migrations.CreateUsers do
use Ecto.Migration
def change do
create table(:users, primary_key: false) do # <-- ここ修正
add :id, :uuid, primary_key: true # <-- この行を追加
add :email, :string
add :name, :string
timestamps()
end
end
end
以上で完了です。
マイグレーション
mix ecto.migrate
試す
phoenixを起動して、ユーザー登録をしてみましょう。
mix phx.server
別のシェルを立ち上げて、以下のようにpostでユーザー追加してみます。
curl -H 'Content-Type: application/json' -X POST -d '{"user": {"email":"neo@matrix.com", "name": "Thomas A. Anderson"}}' localhost:4000/api/users
# レスポンス
{"data":{"name":"Thomas A. Anderson","id":"304ec98a-7cd4-4c28-9aa8-80ad2e1c8ee5","email":"neo@matrix.com"}}
このようにレスポンスが返ってくれば、成功です。もちろんuuidなので、idの文字列は上記と違うはずです。
curlでGETするか、localhost:4000/api/usersにアクセスすると、登録されたユーザーのjsonデータを確認できます。