-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 63c7307
Showing
20 changed files
with
560 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Generated by Cargo | ||
# will have compiled files and executables | ||
debug/ | ||
target/ | ||
|
||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||
Cargo.lock | ||
|
||
# These are backup files generated by rustfmt | ||
**/*.rs.bk | ||
|
||
# MSVC Windows builds of rustc generate these, which store debugging information | ||
*.pdb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "sea-orm-rocket-example" | ||
version = "0.1.0" | ||
authors = ["Vojtěch Jungmann", "Sebastian Pravda"] | ||
edition = "2021" | ||
publish = false | ||
|
||
[workspace] | ||
members = [".", "api", "core", "entity", "migration"] | ||
|
||
[dependencies] | ||
portfolio-api = { path = "api" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#[default] | ||
#template_dir = "api/templates/" | ||
|
||
[default.databases.sea_orm] | ||
#url = "postgres://root:root@localhost/rocket_example" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
[package] | ||
name = "portfolio-api" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
async-stream = { version = "^0.3" } | ||
async-trait = { version = "0.1" } | ||
futures = { version = "^0.3" } | ||
futures-util = { version = "^0.3" } | ||
rocket = { version = "0.5.0-rc.2", features = [ | ||
"json", | ||
] } | ||
|
||
serde_json = { version = "^1" } | ||
|
||
portfolio-entity = { path = "../entity" } | ||
portfolio-migration = { path = "../migration" } | ||
portfolio-core = { path = "../core" } | ||
|
||
tokio = "1.21.2" | ||
|
||
[dependencies.sea-orm-rocket] | ||
version = "0.5.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#[macro_use] | ||
extern crate rocket; | ||
|
||
use rocket::fairing::{self, AdHoc}; | ||
use rocket::form::{ Form}; | ||
use rocket::fs::{relative, FileServer}; | ||
use rocket::response::{Flash, Redirect}; | ||
use rocket::{Build, Rocket}; | ||
use portfolio_core::{Mutation, Query}; | ||
|
||
use migration::MigratorTrait; | ||
use sea_orm_rocket::{Connection, Database}; | ||
|
||
mod pool; | ||
use pool::Db; | ||
|
||
pub use entity::post; | ||
pub use entity::post::Entity as Post; | ||
|
||
|
||
#[post("/", data = "<post_form>")] | ||
async fn create(conn: Connection<'_, Db>, post_form: Form<post::Model>) -> Flash<Redirect> { | ||
let db = conn.into_inner(); | ||
|
||
let form = post_form.into_inner(); | ||
|
||
Mutation::create_post(db, form) | ||
.await | ||
.expect("could not insert post"); | ||
|
||
Flash::success(Redirect::to("/"), "Post successfully added.") | ||
} | ||
|
||
#[post("/<id>", data = "<post_form>")] | ||
async fn update( | ||
conn: Connection<'_, Db>, | ||
id: i32, | ||
post_form: Form<post::Model>, | ||
) -> Flash<Redirect> { | ||
let db = conn.into_inner(); | ||
|
||
let form = post_form.into_inner(); | ||
|
||
Mutation::update_post_by_id(db, id, form) | ||
.await | ||
.expect("could not update post"); | ||
|
||
Flash::success(Redirect::to("/"), "Post successfully edited.") | ||
} | ||
|
||
#[delete("/<id>")] | ||
async fn delete(conn: Connection<'_, Db>, id: i32) -> Flash<Redirect> { | ||
let db = conn.into_inner(); | ||
|
||
Mutation::delete_post(db, id) | ||
.await | ||
.expect("could not delete post"); | ||
|
||
Flash::success(Redirect::to("/"), "Post successfully deleted.") | ||
} | ||
|
||
#[delete("/")] | ||
async fn destroy(conn: Connection<'_, Db>) -> Result<(), rocket::response::Debug<String>> { | ||
let db = conn.into_inner(); | ||
|
||
Mutation::delete_all_posts(db) | ||
.await | ||
.map_err(|e| e.to_string())?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn run_migrations(rocket: Rocket<Build>) -> fairing::Result { | ||
let conn = &Db::fetch(&rocket).unwrap().conn; | ||
let _ = migration::Migrator::up(conn, None).await; | ||
Ok(rocket) | ||
} | ||
|
||
#[tokio::main] | ||
async fn start() -> Result<(), rocket::Error> { | ||
rocket::build() | ||
.attach(Db::init()) | ||
.attach(AdHoc::try_on_ignite("Migrations", run_migrations)) | ||
//.mount("/", FileServer::from(relative!("/static"))) | ||
.mount("/", routes![create, delete, destroy, update]) | ||
.register("/", catchers![]) | ||
.launch() | ||
.await | ||
.map(|_| ()) | ||
} | ||
|
||
pub fn main() { | ||
let result = start(); | ||
|
||
println!("Rocket: deorbit."); | ||
|
||
if let Some(err) = result.err() { | ||
println!("Error: {}", err); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use portfolio_core::sea_orm; | ||
|
||
use async_trait::async_trait; | ||
use sea_orm::ConnectOptions; | ||
use sea_orm_rocket::{rocket::figment::Figment, Config, Database}; | ||
use std::time::Duration; | ||
|
||
#[derive(Database, Debug)] | ||
#[database("sea_orm")] | ||
pub struct Db(SeaOrmPool); | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct SeaOrmPool { | ||
pub conn: sea_orm::DatabaseConnection, | ||
} | ||
|
||
#[async_trait] | ||
impl sea_orm_rocket::Pool for SeaOrmPool { | ||
type Error = sea_orm::DbErr; | ||
|
||
type Connection = sea_orm::DatabaseConnection; | ||
|
||
async fn init(figment: &Figment) -> Result<Self, Self::Error> { | ||
let config = figment.extract::<Config>().unwrap(); | ||
let mut options: ConnectOptions = config.url.into(); | ||
options | ||
.max_connections(config.max_connections as u32) | ||
.min_connections(config.min_connections.unwrap_or_default()) | ||
.connect_timeout(Duration::from_secs(config.connect_timeout)); | ||
if let Some(idle_timeout) = config.idle_timeout { | ||
options.idle_timeout(Duration::from_secs(idle_timeout)); | ||
} | ||
let conn = sea_orm::Database::connect(options).await?; | ||
|
||
Ok(SeaOrmPool { conn }) | ||
} | ||
|
||
fn borrow(&self) -> &Self::Connection { | ||
&self.conn | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
[package] | ||
name = "portfolio-core" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
portfolio-entity = { path = "../entity" } | ||
|
||
[dependencies.sea-orm] | ||
version = "^0.10.0" | ||
features = [ | ||
"runtime-tokio-native-tls", | ||
"sqlx-postgres", | ||
"sqlx-sqlite", | ||
] | ||
|
||
[dev-dependencies] | ||
tokio = "1.21.2" | ||
|
||
[features] | ||
mock = ["sea-orm/mock"] | ||
|
||
[[test]] | ||
name = "mock" | ||
required-features = ["mock"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
mod mutation; | ||
mod query; | ||
|
||
pub use mutation::*; | ||
pub use query::*; | ||
|
||
pub use sea_orm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use ::entity::{post, post::Entity as Post}; | ||
use sea_orm::*; | ||
|
||
pub struct Mutation; | ||
|
||
impl Mutation { | ||
pub async fn create_post( | ||
db: &DbConn, | ||
form_data: post::Model, | ||
) -> Result<post::ActiveModel, DbErr> { | ||
post::ActiveModel { | ||
title: Set(form_data.title.to_owned()), | ||
text: Set(form_data.text.to_owned()), | ||
..Default::default() | ||
} | ||
.save(db) | ||
.await | ||
} | ||
|
||
pub async fn update_post_by_id( | ||
db: &DbConn, | ||
id: i32, | ||
form_data: post::Model, | ||
) -> Result<post::Model, DbErr> { | ||
let post: post::ActiveModel = Post::find_by_id(id) | ||
.one(db) | ||
.await? | ||
.ok_or(DbErr::Custom("Cannot find post.".to_owned())) | ||
.map(Into::into)?; | ||
|
||
post::ActiveModel { | ||
id: post.id, | ||
title: Set(form_data.title.to_owned()), | ||
text: Set(form_data.text.to_owned()), | ||
} | ||
.update(db) | ||
.await | ||
} | ||
|
||
pub async fn delete_post(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { | ||
let post: post::ActiveModel = Post::find_by_id(id) | ||
.one(db) | ||
.await? | ||
.ok_or(DbErr::Custom("Cannot find post.".to_owned())) | ||
.map(Into::into)?; | ||
|
||
post.delete(db).await | ||
} | ||
|
||
pub async fn delete_all_posts(db: &DbConn) -> Result<DeleteResult, DbErr> { | ||
Post::delete_many().exec(db).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
use ::entity::{post, post::Entity as Post}; | ||
use sea_orm::*; | ||
|
||
pub struct Query; | ||
|
||
impl Query { | ||
pub async fn find_post_by_id(db: &DbConn, id: i32) -> Result<Option<post::Model>, DbErr> { | ||
Post::find_by_id(id).one(db).await | ||
} | ||
|
||
/// If ok, returns (post models, num pages). | ||
pub async fn find_posts_in_page( | ||
db: &DbConn, | ||
page: u64, | ||
posts_per_page: u64, | ||
) -> Result<(Vec<post::Model>, u64), DbErr> { | ||
// Setup paginator | ||
let paginator = Post::find() | ||
.order_by_asc(post::Column::Id) | ||
.paginate(db, posts_per_page); | ||
let num_pages = paginator.num_pages().await?; | ||
|
||
// Fetch paginated posts | ||
paginator.fetch_page(page - 1).await.map(|p| (p, num_pages)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
mod prepare; | ||
|
||
use entity::post; | ||
use prepare::prepare_mock_db; | ||
use rocket_example_core::{Mutation, Query}; | ||
|
||
#[tokio::test] | ||
async fn main() { | ||
let db = &prepare_mock_db(); | ||
|
||
{ | ||
let post = Query::find_post_by_id(db, 1).await.unwrap().unwrap(); | ||
|
||
assert_eq!(post.id, 1); | ||
} | ||
|
||
{ | ||
let post = Query::find_post_by_id(db, 5).await.unwrap().unwrap(); | ||
|
||
assert_eq!(post.id, 5); | ||
} | ||
|
||
{ | ||
let post = Mutation::create_post( | ||
db, | ||
post::Model { | ||
id: 0, | ||
title: "Title D".to_owned(), | ||
text: "Text D".to_owned(), | ||
}, | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
post, | ||
post::ActiveModel { | ||
id: sea_orm::ActiveValue::Unchanged(6), | ||
title: sea_orm::ActiveValue::Unchanged("Title D".to_owned()), | ||
text: sea_orm::ActiveValue::Unchanged("Text D".to_owned()) | ||
} | ||
); | ||
} | ||
|
||
{ | ||
let post = Mutation::update_post_by_id( | ||
db, | ||
1, | ||
post::Model { | ||
id: 1, | ||
title: "New Title A".to_owned(), | ||
text: "New Text A".to_owned(), | ||
}, | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
post, | ||
post::Model { | ||
id: 1, | ||
title: "New Title A".to_owned(), | ||
text: "New Text A".to_owned(), | ||
} | ||
); | ||
} | ||
|
||
{ | ||
let result = Mutation::delete_post(db, 5).await.unwrap(); | ||
|
||
assert_eq!(result.rows_affected, 1); | ||
} | ||
|
||
{ | ||
let result = Mutation::delete_all_posts(db).await.unwrap(); | ||
|
||
assert_eq!(result.rows_affected, 5); | ||
} | ||
} |
Oops, something went wrong.