Rust入門 初心者がYouTube生放送でWeb開発 3時間目

YouTubeの生放送でRustを勉強中なのですが、そこでRustを勉強してわかったことを書いていきます。

放送アーカイブ↓
[<img width="520" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751408/9b461213-eaa6-d2a8-467e-aa0ac707c03c.jpeg">](https://youtu.be/z0O256mOYKU)
[【生放送アーカイブ】 Rust でWeb開発に入門しました② 苦しみながらデータベースにアクセス…大変でした…](https://youtu.be/z0O256mOYKU)
https://youtu.be/z0O256mOYKU

## 前の記事

[Rust入門 初心者がYouTube生放送でWeb開発入門 1時間目, 2時間目](https://qiita.com/yassun-youtube/items/bd0ae95f7c537b19d3a8)
https://qiita.com/yassun-youtube/items/bd0ae95f7c537b19d3a8

## Rust での Database アクセス

公式ページには、下記のいずれかを選ぶと良いと書いてある。

![スクリーンショット 2020-10-17 15.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751408/d2a79a98-ffde-4009-839c-db9304a57d66.png)


https://rocket.rs/v0.4/guide/state/#databases

MySQLを使いたいので、Diesel というのを選択

## Dieselの使い方

公式ページで Getting Started.

https://diesel.rs/guides/getting-started/

Cargo.tomlを編集

``` Cargo.toml
[dependencies]
diesel = { version = "1.4.4", features = ["mysql"] }
dotenv = "0.15.0"
```

### diesel cli をインストール

migrationなどに必要

```bash
cargo install diesel_cli
```

### .envを用意

```bash
echo DATABASE_URL=mysql://username:password@localhost/diesel_demo > .env
```

### Databaseのセットアップ

```
diesel setup
```

### Migrationファイルの作成

```
diesel migration generate create_posts
```

`migrations/` フォルダにファイルが作成される。

```up.sql
CREATE TABLE posts (
  id INT PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  body TEXT NOT NULL,
  published BOOLEAN NOT NULL
)
```


```down.sql
DROP TABLE posts;
```

### Migrationの実行

```bash
diesel migration run
```

なお、migrationコマンドは、

```bash
diesel migration revert # rollback
diesel migration redo # ロールバックしつつ再度migrate
```

などがあるようだ

## Rocketに設定を追加

```Rocket.toml
[global.databases.my_db]
url = "mysql://root:@localhost/diesel_demo"
```

```src/lib.rs
#[macro_use]
extern crate diesel;
extern crate dotenv;

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

pub mod schema;
pub mod models;
```

```src/models.rs
#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}
```

## GET で Post を取得する処理を書いてみる


```src/main.rs
#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;


use rocket::http::RawStr;
use rocket::Request;
use serde::Serialize;
use rocket_contrib::json::Json;
use rocket_contrib::databases::diesel;
use self::hello_rocket::models::Post;
use diesel::prelude::*;


#[database("my_db")]
struct MyDbConn(diesel::MysqlConnection);

#[get("/posts/<_id>")]
fn get_post(conn: MyDbConn, _id: i32) -> String {
    use hello_rocket::schema::posts::dsl::*;

    let result = posts.find(_id)
        .first::<Post>(&*conn);
    match result {
        Ok(v) => format!("Post {}", v.title),
        Err(e) => format!("{}", e)
    }
}

fn main() {
    rocket::ignite().mount("/", routes![get_post])
                    .attach(MyDbConn::fairing())
                    .launch();
}
```

データベースで `posts` テーブルにデータを作成（id = 1）

これで、 `cargo run` をして`http://localhost:8000/posts/1` にアクセスすると `Post <title>` が表示される。


たったこれだけのために今回の生放送はめっちゃ大変だった…。
実際の苦しみながらやる様子を見てみたいという方は動画を見てください :bow: