🎨

database.build (formerly postgres.new)にrails db:migrateしてER図を眺めたりしてみる

2024/10/19に公開

軽いネタです。

database.build (formerly postgres.new) とは

database.build(旧称:postgres.new は、PostgreSQL データベースを簡単に構築・管理するためのプラットフォームです。

https://database.build/

GitHubアカウントでログインすると、ブラウザ上でPostgreSQLが立ち上がり(!)、playground的にいろいろ遊べます。
立ち上がるPostgreSQLは、WASMに移植した PGlite を活用して実装しているとのこと。データは、ブラウザ内のIndexedDBに保存されるとのことです [1]

よくある使い方: 対話的にDB設計ができる

たとえばチャット欄に「メルカリみたいなやつ」といれると、そんな感じのものをLLMが作ってくれます。

対話の様子はこんな感じ。animation gif:

画面上の主な機能としては

  • E-R図が確認できる
  • migrationのためのCREATE TABLE文が確認できる

ということがあります。

また、ダウンロードボタンを押せば、IndexedDBの中身が全部.gzファイルで降ってきます。中身はPostgresの実体ファイルたち。

LiveShare機能でpsql接続できる

LiveShareボタンがあるのでおもむろにこれを押すと

LiveShare

こんな感じで、psqlとかで接続可能なURLを払い出してくれます。

接続先ホストとなっている *.browser.db.build を利用するにはインターネットが必要です。 (現状 fly.io が使われている雰囲気。)

これでpsqlで、お手元のブラウザ上で立ち上がっているPostgreSQL(PGLite)に接続できます。

しくみについてはよく理解していませんが、supabaseのブログに書いてあります [2]
websocketとsql接続用のTCPを仲立ちするproxyがインターネット上にある様子。以下はそのブログからの引用。

今回やってみたこと: railsのタスクでアクセス

空のデータベースを作成・接続先URLをゲット

最初に対話が必要で、「空のデータベース」とか入力するとデータベースを作ってくれます。

LiveShareボタンを押して接続先URLをコピっておきます。

このときブラウザのタブは開いたままで。

rails db:migrateしてみる

手元に適当なrailsアプリがあれば試せます。

自分が動作確認したRailsアプリをログがてら置いておきます:

https://github.com/hoshinotsuyoshi/zenn-memo-2024-10-19

自分の環境では以下のような前提が必要でした。

  • postgresベースであること
  • pg gemをビルドしたときに使ったライブラリが比較的新しいものであること
    • (postgres16とかだったら問題ないはず。postgres11ベースだとSNIを使うためか動かなかった)

今回 の db/schema.rb はこんな感じ。Eコマースっぽいものにしてみました。 [3]

ActiveRecord::Schema[8.0].define(version: 7) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "pg_catalog.plpgsql"

  create_table "cart_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.uuid "cart_id", null: false
    t.uuid "product_id", null: false
    t.string "product_name", null: false
    t.decimal "product_unit_price", default: "0.0", null: false
    t.integer "quantity", default: 0, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["cart_id"], name: "index_cart_items_on_cart_id"
    t.index ["product_id"], name: "index_cart_items_on_product_id"
  end

  create_table "carts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.uuid "user_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_carts_on_user_id"
  end

  create_table "products", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.string "name", null: false
    t.text "description", null: false
    t.decimal "unit_price", default: "0.0", null: false
    t.integer "stock", default: 0, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "purchases", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.uuid "cart_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["cart_id"], name: "index_purchases_on_cart_id"
  end

  create_table "sessions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.uuid "user_id", null: false
    t.string "ip_address"
    t.string "user_agent"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_sessions_on_user_id"
  end

  create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
    t.string "email_address", null: false
    t.string "password_digest", null: false
    t.string "onboarding_status", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email_address"], name: "index_users_on_email_address", unique: true
  end

  add_foreign_key "sessions", "users"
end

rails db:migrateは以下のようなコマンドで実行しました。

なんとなく RAILS_ENV=test していますが、これはなくてもいいかも。

RAILS_ENV=test DATABASE_URL="<URLをここで利用>" bin/rails db:migrate

ちなみに接続先は米国っぽかったのでだいぶ遅いです。

超時間かかりますがrspecでdbを使うような簡単なテストも動きました。

E-R図に反映された様子を確認

E-R図にちゃんと反映されます。

今回外部キーは1つしか設定してないので、Entity同士のつながりの線は少なくなっています。

チャットでテーブルを説明させる

「今存在するテーブルを説明してください」とか入力すると、返事で教えてくれます

結び

今回は、database.build を使って、手軽にPostgreSQLデータベースを作成し、Railsの db:migrate を実行してE-R図を眺めてみる、という軽めの実験をしてみました。

米国のサーバーに接続するせいか遅延はあるものの、ブラウザだけで完結する手軽さが魅力ですね。
プロキシもフロントエンドアプリもOSSなので [4]、機会があればセルフホストしてみようかと思いました

脚注
  1. https://supabase.com/blog/postgres-new ↩︎

  2. https://supabase.com/blog/database-build-live-share ↩︎

  3. 記憶が定かじゃないけど enable_extension "pgcrypto" はあると不都合だった気がするので削除して調整した。それでも動かなかったらすいません。 ↩︎

  4. https://github.com/supabase-community/postgres-new ↩︎

Discussion