Rust dieselクレイトを運用中既存DBに適用したので、手順をメモしておきます。
依存関係の定義
データベーススキーマは通常通りDATABASE_URLに定義しておく。
自分の場合は.env
に記載しておいた。
DATABASE_URL=postgresql://postgres:password@localhost:5432/databasename
Cargo.toml
[dependencies] dotenv = "0.15" diesel = { version = "1.4.4", features = ["postgres", "chrono"] }
diesel-cli
のインストールは省略。
運用中のデータベースには以下のテーブルがすでに存在するものとします。
CREATE TABLE users ( id SERIAL PRIMARY KEY, email TEXT NOT NULL, password TEXT NOT NULL, created_at timestamp default now() )
dieselのセットアップ
$ diesel setup
と行っても自分の検証環境では既存DBを壊すような挙動は行いませんでした。
追記:すでにDiesel用のmigrationディレクトリとmigrationファイルがプロジェクト内に存在する場合は、migrationの実行が行われる。既存DBに対しては構成をプロジェクトに合わす/既存のまま運用する、のポリシーに応じてmigrationディレクトリの配置/削除を行う。
多分、setup
はDBへmigrationテーブル作成、及びdiesel.toml、migrationディレクトリの作成を行うコマンドだと思うので、今後、migration運用する必要なければ、diesel.tomlを手動で作成して、この手順すらスキップできるような気がする。試してないけど。
既存DBへのつなぎこみ
公式ドキュメント通りに記述すれば簡単に接続できる。
use diesel::pg::PgConnection; use dotenv::dotenv; pub fn establish_connection() -> PgConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL") .expect("DATABASE_URL must be set"); PgConnection::establish(&database_url) .expect(&format!("Error connecting to {}", database_url)) }
https://diesel.rs/guides/getting-started/
ORMの準備
ORMを利用するには、Resultを格納するモデルとテーブルレイアウトのschema.rsを作成する。要はmigration時に自動で作成されるschema.rsを既存テーブルのレイアウトに応じて自身で作成する。ということ。
models.rs
use crate::schema::*; use chrono::NaiveDateTime; #[derive(Clone, Queryable)] pub struct User { pub id: i32, pub email: String, pub password: String, pub created_at: NaiveDateTime, }
schema.rs
table! { users (id) { id -> Integer, email -> Text, password -> Text, created_at -> Timestamp, } }
上記で、ORMを扱う準備が整った。
dieselを通してテーブルアクセスを行う
あとは通常通りの使い方で利用すればよい。
#[macro_use] extern crate diesel; extern crate dotenv; use diesel::prelude::*; use diesel::pg::PgConnection; use dotenv::dotenv; use std::env; pub mod schema; pub mod models; use models::*; async fn index() -> String { use schema::users::dsl::*; let connection = establish_connection(); let results = users.load::<User>(&connection).expect("error loading users"); let mut user_name = "Not Found User".to_string(); if let user = results.first().unwrap() { user_name = user.email.clone(); } format!( "DB Record {}", user_name ) }
サンプルコード github.com
多分、schema.rsで解釈可能なテーブルレイアウトな限りORM利用できると思う。命名規則で使えないってことはないんじゃないかな。試してないけど笑