LoginSignup
17
10

More than 3 years have passed since last update.

Rust の ORM「Diesel」とたわむれてみた。

Posted at

諸注意

  • Rust超初心者です。お手柔らかにお願いします。
  • いつもはpythonとC++を使うことが多いですが、Rust書いてみたかったので触ってみました。
  • RustのORMについて何があるんだろうと調べて、どうやら「Diesel」とういうものがあると知り、使い勝手はどんなものか簡単に調べてみました。

やったこと

  • gitにあるDieselのexampleコードを追いかけてみました。
    • sqliteにdieselのマイグレーションでテーブルを作る。
    • 手でサンプルデータをインサートする。
    • diselからコネクションを作って、データの一覧を受け取る。

また、こちらdieselのサンプル(sqlite)を動かしてみたを参考にさせていただきました。素晴らしい記事をありがとうございます!!

rustの環境

$ rustc --version
rustc 1.40.0-nightly (1423bec54 2019-11-05)

感想

  • Dieselはそれに比べて少しドキュメントが少ないし、本家のgitのexampleもけっこうバグが出て悲しみが多い。(Dieselのexampleコード)

チュートリアルでバグが出るのはきついですよね、下のコードは下の環境下で動くことを確認済みなので、ぜひご活用ください!!
これからRust勉強していきます。
「いいね」や「コメント」お待ちしております!!

Diesel

いつものごとくプロジェクトを作ります。

cargo new web_diesel

Cargo.toml

[dependencies]
rocket="0.4"
rocket_contrib={version="0.4", features=["json"]}
serde = {version="1.0", features=["derive"]}
serde_json="1.0.0"
diesel = { version = "1.4.0", features = ["sqlite"] }
dotenv = "0.10"

データベースを作ります。
これでsample.dbというsqliteのファイルができます。

$ echo DATABASE_URL=./sample.db > .env
$ diesel setup

マイグレーションをします。

$ diesel migration generate create_posts

できたマイグレーションフォルダのup.sqlに

up.sql
CREATE TABLE posts (
  id INTEGER NOT NULL PRIMARY KEY,
  title VARCHAR NOT NULL,
  body TEXT NOT NULL,
  published BOOLEAN NOT NULL DEFAULT 0
)

down.sqlに

down.sql
DROP TABLE posts

と書く。

ここで、フォルダの中は

$ls
Cargo.lock   Cargo.toml   diesel.toml  migrations/  sample.db    src/         target/
tree src
src
├── main.rs
├── models.rs
├── sample.db
├── schema.rs

となっている。

main.rs

#[macro_use]
extern crate diesel;

use web_diesel::models::*;
use diesel::prelude::*;

#[macro_use]
extern crate dotenv;

// models.rsとschema.rsのインポート
pub mod models;
pub mod schema;

use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

//Sqliteコネクションを作る。
pub fn establish_connection() -> SqliteConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    SqliteConnection::establish(&database_url)
        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}

//レコードをすべて受け取る。
fn main() {
    use web_diesel::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);
    }
}

models.rs

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}

schema.rs

table! {
    posts (id) {
        id -> Integer,
        title -> Text,
        body -> Text,
        published -> Bool,
    }
}

とりあえず、手でデータをインサートして、ORMで全件取得ということをしてみます。

$sqlite3 sample.db
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite> .table
__diesel_schema_migrations  posts                     
sqlite> insert into posts values(1,"title1", "body1",0);

という感じで五件くらい入れてみます。

$sqlite3 sample.db
sqlite> select * from posts;
1|title1|body1|0
2|title2|body2|0
3|title3|body3|0
4|title4|body4|0
5|title5|body5|0
sqlite> 

が確認できたら、
プロジェクトリポジトリ直下(sample.dbがある場所)で、

cargo run

    Finished dev [unoptimized + debuginfo] target(s) in 0.07s
     Running `target/debug/web_diesel`
Displaying 5 posts
title1
----------

body1
title2
----------

body2
title3
----------

body3
title4
----------

body4
title5
----------

body5

とレコードが取得できるのを確認できました。

後日もっといろいろやってみたいと思います!!

17
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
10