feat: migration and project structure

This commit is contained in:
Kilerd Chan 2018-09-14 00:35:12 +08:00
parent 42ed14c632
commit 1da5c49dfb
10 changed files with 131 additions and 6 deletions

View File

@ -7,4 +7,11 @@ license = "MIT"
[dependencies] [dependencies]
rocket = "0.3.16" rocket = "0.3.16"
rocket_codegen = "0.3.16" rocket_codegen = "0.3.16"
rocket_contrib = "0.3"
diesel = { version = "1.0.0", features = ["postgres", "r2d2"] }
dotenv = "0.9.0"
r2d2 = "0.8"
lazy_static = "1.1"
serde = "1.0"
serde_derive = "1.0"

View File

@ -1,5 +1,2 @@
[global] [global]
template_dir = "static" template_dir = "static"
[global.databases.sqlite_database]
url = "db/db.sqlite"

0
migrations/.gitkeep Normal file
View File

View File

@ -0,0 +1,6 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
DROP FUNCTION IF EXISTS diesel_set_updated_at();

View File

@ -0,0 +1,36 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.
-- Sets up a trigger for the given table to automatically set a column called
-- `updated_at` whenever the row is modified (unless `updated_at` was included
-- in the modified columns)
--
-- # Example
--
-- ```sql
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
--
-- SELECT diesel_manage_updated_at('users');
-- ```
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
BEGIN
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
BEGIN
IF (
NEW IS DISTINCT FROM OLD AND
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
) THEN
NEW.updated_at := current_timestamp;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

View File

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE posts

View File

@ -0,0 +1,7 @@
-- Your SQL goes here
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body TEXT NOT NULL,
published BOOLEAN NOT NULL DEFAULT 'f'
)

View File

@ -1,6 +1,20 @@
#![feature(plugin)] #![feature(plugin)]
#![plugin(rocket_codegen)] #![plugin(rocket_codegen)]
extern crate rocket; extern crate rocket;
extern crate diesel;
extern crate dotenv;
extern crate r2d2;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
mod pg_pool;
mod schema;
use dotenv::dotenv;
#[get("/")] #[get("/")]
fn index() -> String { fn index() -> String {
@ -8,5 +22,11 @@ fn index() -> String {
} }
fn main() { fn main() {
rocket::ignite().mount("/",routes![index]).launch(); dotenv().ok();
let database_url = std::env::var("database_url").expect("database_url must be set");
rocket::ignite()
.manage(pg_pool::init(&database_url))
.mount("/",routes![index])
.launch();
} }

42
src/pg_pool.rs Normal file
View File

@ -0,0 +1,42 @@
use diesel::pg::PgConnection;
use r2d2;
use diesel::r2d2::ConnectionManager;
type ManagedPgConn = ConnectionManager<PgConnection>;
type Pool = r2d2::Pool<ManagedPgConn>;
use rocket::http::Status;
use rocket::request::{self, FromRequest};
use rocket::{Outcome, Request, State};
use std::ops::Deref;
/// Db Connection request guard type: wrapper around r2d2 pooled connection
pub struct DbConn(pub r2d2::PooledConnection<ManagedPgConn>);
/// Attempts to retrieve a single connection from the managed database pool. If
/// no pool is currently managed, fails with an `InternalServerError` status. If
/// no connections are available, fails with a `ServiceUnavailable` status.
impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<DbConn, ()> {
let pool = request.guard::<State<Pool>>()?;
match pool.get() {
Ok(conn) => Outcome::Success(DbConn(conn)),
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
}
}
}
// For the convenience of using an &DbConn as an &SqliteConnection.
impl Deref for DbConn {
type Target = PgConnection;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub fn init(database_url: &str) -> Pool {
let manager = ConnectionManager::<PgConnection>::new(database_url);
r2d2::Pool::new(manager).expect("Failed to create pool.")
}

8
src/schema.rs Normal file
View File

@ -0,0 +1,8 @@
table! {
posts (id) {
id -> Int4,
title -> Varchar,
body -> Text,
published -> Bool,
}
}