はじめに
- Elixir楽しんでいますか
- Active Record(Ruby)でmigrateした内容とぴったり同じものをEcto(Elixir)でマイグレーションファイルを書きたいということがありました
- データベースはPostgreSQLを使いました
- ググってみてもなかなか答えは見つかりませんでした
- この記事を書く途中で、ようやく公式にも記述があるにはあることを発見しました
- https://hexdocs.pm/ecto_sql/Ecto.Migration.html#module-field-types
- ただなかなかここにたどり着けませんでした
- 特定のActive Record(Ruby)のマイグレーションファイルを正解(期待)として、なんとなくカンでEcto(Elixir)のマイグレーションファイルを書いてみたら一致したのでそのことを記事に残しておきます
- 使用したライブラリなどのバージョンは以下の通りです
バージョン | バージョン確認コマンド | |
---|---|---|
PostgreSQL | 13.2 | psql --version |
Ruby | 2.6.2 | ruby -v |
Active Record | 5.2.4.1 | cat Gemfile.lock |
Elixir | 1.9.4 | elixir -v |
Ecto | 3.3.4 | cat mix.lock |
Active Record(Ruby)のマイグレーションファイル
# frozen_string_literal: true
class DeviseCreateAdminUsers < ActiveRecord::Migration[5.2]
def change
create_table :admin_users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.inet :current_sign_in_ip
# t.inet :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :admin_users, :email, unique: true
add_index :admin_users, :reset_password_token, unique: true
# add_index :admin_users, :confirmation_token, unique: true
# add_index :admin_users, :unlock_token, unique: true
end
end
- Deviseです
- https://github.com/heartcombo/devise/graphs/contributors
- のページをみるとElixirの作者José Valimさんのお名前がみえます
- このマイグレーションファイルを
bin/rails db:migrate
でマイグレートしてみると、以下のテーブルがつくられます
$ psql -U postgres
postgres=# \c workflows_repo
workflows_repo=# \d admin_users
Table "public.admin_users"
Column | Type | Collation | Nullable | Default
------------------------+-----------------------------+-----------+----------+-----------------------------------------
id | bigint | | not null | nextval('admin_users_id_seq'::regclass)
email | character varying | | not null | ''::character varying
encrypted_password | character varying | | not null | ''::character varying
reset_password_token | character varying | | |
reset_password_sent_at | timestamp without time zone | | |
remember_created_at | timestamp without time zone | | |
created_at | timestamp without time zone | | not null |
updated_at | timestamp without time zone | | not null |
Indexes:
"admin_users_pkey" PRIMARY KEY, btree (id)
"index_admin_users_on_email" UNIQUE, btree (email)
"index_admin_users_on_reset_password_token" UNIQUE, btree (reset_password_token)
Ecto(Elixir)マイグレーションファイル
- ぴったり一致するEctoのマイグレーションファイルは以下のようになります
defmodule Workflows.Repo.Migrations.CreateAdminUsers do
use Ecto.Migration
def change do
create table(:admin_users) do
add :email, :"character varying", default: "", null: false
add :encrypted_password, :"character varying", default: "", null: false
add :reset_password_token, :"character varying", size: nil
add :reset_password_sent_at, :"timestamp without time zone"
add :remember_created_at, :"timestamp without time zone"
add :created_at, :"timestamp without time zone", null: false
add :updated_at, :"timestamp without time zone", null: false
end
create unique_index(:admin_users, [:email], name: :index_admin_users_on_email)
create unique_index(:admin_users, [:reset_password_token], name: :index_admin_users_on_reset_password_token)
end
end
- Typeを指定するところに、
psql
で確認した:"character varying"
、:"timestamp without time zone"
とカンで書いてみるとぴったり一致しました - インデックスの名前は、
:name
で指定しました
一致しないマイグレーションファイル
defmodule Workflows.Repo.Migrations.CreateAdminUsers do
use Ecto.Migration
def change do
create table(:admin_users) do
add :email, :string, default: "", null: false
add :encrypted_password, :string, default: "", null: false
add :reset_password_token, :string, size: nil
add :reset_password_sent_at, :utc_datetime
add :remember_created_at, :utc_datetime
add :created_at, :utc_datetime, null: false
add :updated_at, :utc_datetime, null: false
end
create unique_index(:admin_users, [:email])
create unique_index(:admin_users, [:reset_password_token])
end
end
- Typeを
:string
、:utc_datetime
にしてmix ecto.migrate
すると以下のように少し異なったものがつくられます - インデックスの名前は、
:name
オプションを指定しない場合、少し異なっています
Table "public.admin_users"
Column | Type | Collation | Nullable | Default
------------------------+--------------------------------+-----------+----------+-----------------------------------------
id | bigint | | not null | nextval('admin_users_id_seq'::regclass)
email | character varying(255) | | not null | ''::character varying
encrypted_password | character varying(255) | | not null | ''::character varying
reset_password_token | character varying(255) | | |
reset_password_sent_at | timestamp(0) without time zone | | |
remember_created_at | timestamp(0) without time zone | | |
created_at | timestamp(0) without time zone | | not null |
updated_at | timestamp(0) without time zone | | not null |
Indexes:
"admin_users_pkey" PRIMARY KEY, btree (id)
"admin_users_email_index" UNIQUE, btree (email)
"admin_users_reset_password_token_index" UNIQUE, btree (reset_password_token)
- https://hexdocs.pm/ecto_sql/Ecto.Migration.html#module-field-types
- によると、
:string
は255文字を上限とすると書いてありまして、そのとおりになっています-
:size
オプションで指定することができます
-
Wrapping up
- この記事を書く前は、どこにも書いてなかったので記事にしました〜 というつもりで書いていました
- https://hexdocs.pm/ecto_sql/Ecto.Migration.html#module-field-types をよく見ると、この記事で紹介したようなTypeの指定方法が書いてありました
- どなたかのお役に立てることがあるかもしれませんので記事を残しておきます
-
character varying no limit postgres ecto
とかで検索しましたがなかなかヒットしなかったので
-
- まとめとしては、以下の手順でやればよいです
- 正解(期待)スキーマを確認する
- EctoのマイグレーションファイルでTypeはスキーマに書いてある型をAtomで指定する
- Enjoy Elixir
- この記事は、2021/07/17(土) 00:00 〜 2021/07/19(月) 23:59開催のautoracex #37という純粋なもくもく会での成果です