Elixir Phoenix (小ネタ) プライマリキー名を変えたりあれこれ


やりたいこと

主キー名をidから変えたい。intじゃなくてbigintにしたい。複合キーもできたらやってみたい。

なぜやりたい?

業務で使いたいなーと思ってるけど、
主キーにテーブル名をつけたい (例えばcustomerテーブルの主キーをcustomer_idとかcst_idとかにしたい) 人がいたりするんで
この辺解決しないと抵抗されると思ったから。

ということでやってみます

customerテーブルのキー名をidからcst_idに変更してみます

まずはphx.gen.htmlでテンプレートもろもろ作成

※phoenixのプロジェクトは作成済みの想定です

$ mix phx.gen.html People Customer customers cst_name:string cst_email:string

migrationファイルの編集

priv/repo/migrations/<日付+タイムスタンプ>_create_customers.exsを開いて、以下のように設定

  def change do
    create table(:customers, primary_key: false) do
      add :cst_id, :integer, primary_key: true
      add :cst_name, :string
      add :cst_email, :string
      timestamps()
    end
  end

create table(:customers, primary_key: false)
add :cst_id, :integer, primary_key: trueがポイントのようです。
デフォルトをOFFにして、かわりに任意のカラムをONにしているような感じでしょうか?

migrationの実行

mix ecto.migrate

schmeに設定追加

モジュールdefmodule <アプリ名>.<コンテキスト名>.Customerを開いて編集します

<変更前>

  schema "customers" do
    field :cst_email, :string
    field :cst_name, :string

    timestamps()
  end

<変更後>

  @primary_key {:cst_id, :id, autogenerate: true}
  @derive {Phoenix.Param, key: :cst_id}
  schema "customers" do
    field :cst_email, :string
    field :cst_name, :string

    timestamps()
  end

@primary_key@deriveを追加しています。
@primary_keyは主キーフィールド名、タイプ、オプションとなっていて、デフォルトだと
{:id, :id, autogenerate: true}となってるそうです。
https://hexdocs.pm/ecto/Ecto.Schema.html#module-schema-attributes

なんかこれだけでいけそうな雰囲気はしますが実際には
@deriveが必要みたいです。
https://hexdocs.pm/phoenix/Phoenix.Param.html

 ルーティングの追加

idがデフォルトの時と同じように

routes.exscope "/",<アプリ名> do
の中に
elixir
resources "/customers", CustomerController

を追加するだけでOKです。

確認1

サーバーを立ち上げて

iex -S mix phx.server

にアクセスして追加、更新、表示、削除など、普通に出来ました。

確認2

本当にidが変わってるかテーブルを見てみます。
※SQLite3を使用しています。
使い方(手前味噌ですが):https://qiita.com/ko-tk/items/ab5e585d01bbf197c569

idがcst_idになっており、インクリメントされていることがわかります。

以上。

じゃない。複合キーもやってみたいとか言いながら忘れてた。追記。

以下試してないけど、こんな感じで行けるんじゃなかろうか。
見つけてきたのが結構古いバージョンだから確かなことは言えませんが。。
参考:https://phoenixframework.readme.io/docs/ecto-custom-primary-keys

migrationファイル

  def change do
    create table(:customer, primary_key: false) do
      add :cst_no, :string, primary_key: true
      add :cst_type, :string, primary_key: true
      add :name, :string
      add :age, :integer
  . . .

スキーマ

  @primary_key false
  schema "customer" do
    field :cst_no, :string, primary_key: true
    field :cst_type, :string, primary_key: true
    field :name, :string
    field :age, :integer
  . . .