概要
RustのORMではDieselが有名のようなので使ってみた手順のメモです。
基本的に下記の Getting Started の流れを実施しています。
https://diesel.rs/guides/getting-started
プロジェクトの生成
% cargo new diesel_hello_world
% cd diesel_hello_world
Cargo.tomlにdieselとdotenvを追加
[dependencies]
diesel = { version = "1.4.4", features = ["postgres"] }
dotenv = "0.15.0"
dockerでpostgresqlを立て、Databaseを作る
version: "3.9"
services:
postgres:
image: postgres:14.3-alpine3.16
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: password
ports:
- 5432:5432
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
% docker-compose up -d postgres
% psql -h 127.0.0.1 -p 5432 -U username
# create database diesel_demo;
接続用のenv設定をしておく。
echo DATABASE_URL=postgres://username:password@localhost/diesel_demo > .env
diesel_cli のインストール
dieselはcliを持っています。
% cargo install diesel_cli
こちらのコメントでdieselの初期化をします。
% diesel setup
検証用のテーブルを作成する
migrationファイルを生成し、検証用のテーブルの定義を記載します。
% diesel migration generate create_posts
-- migrations/2022-06-01-044213_create_posts/up.sql
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body TEXT NOT NULL,
published BOOLEAN NOT NULL DEFAULT 'f'
)
-- migrations/2022-06-01-044213_create_posts/down.sql
DROP TABLE posts
migrationを実行します。
% diesel migration run
Running migration 2022-06-01-044213_create_posts
psqlで確認します。
# \d posts
Table "public.posts"
Column | Type | Collation | Nullable | Default
-----------+-------------------+-----------+----------+-----------------------------------
id | integer | | not null | nextval('posts_id_seq'::regclass)
title | character varying | | not null |
body | text | | not null |
published | boolean | | not null | false
Indexes:
"posts_pkey" PRIMARY KEY, btree (id)
# select * from __diesel_schema_migrations ;
version | run_on
----------------+----------------------------
00000000000000 | 2022-06-01 04:40:45.143513
20220601044213 | 2022-06-01 04:44:23.940689
(2 rows)
検証用データをinsertしておきます。
# insert into posts values (1, 'title1', 'body1', true), (2, 'title2', 'body2', true);
Rustでselectをするプログラムを作成する
# src/lib.rs
#[macro_use]
extern crate diesel;
extern crate dotenv;
pub mod schema;
pub mod models;
use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
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))
}
# src/models.rs
#[derive(Queryable)]
pub struct Post {
pub id: i32,
pub title: String,
pub body: String,
pub published: bool,
}
# src/bin/show_posts.rs
extern crate diesel_hello_world;
extern crate diesel;
use self::diesel_hello_world::*;
use self::models::*;
use self::diesel::prelude::*;
fn main() {
use diesel_hello_world::schema::posts::dsl::*;
let connection = establish_connection();
let results = posts.filter(published.eq(true))
.limit(5)
.load::<Post>(&connection)
.expect("Error loading posts");
println!("Displaying {} posts", results.len());
for post in results {
println!("{}", post.title);
println!("----------\n");
println!("{}", post.body);
}
}
実行
% cargo run --bin show_posts
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/show_posts`
Displaying 2 posts
title1
----------
body1
title2
----------
body2