Add diesel and example page
This commit is contained in:
parent
1197fe687b
commit
d20ca7cfa9
20 changed files with 453 additions and 14 deletions
|
@ -1,5 +1,4 @@
|
|||
|
||||
use actix_web::{get, Responder, web, HttpResponse};
|
||||
use actix_web::{get, web, HttpResponse, Responder};
|
||||
use yew::ServerRenderer;
|
||||
|
||||
use crate::views::components::hello::{Hello, HelloProps};
|
||||
|
@ -7,8 +6,6 @@ use crate::views::components::hello::{Hello, HelloProps};
|
|||
#[get("/{name}")]
|
||||
async fn index(name: web::Path<String>) -> impl Responder {
|
||||
let name = name.into_inner();
|
||||
let renderer = ServerRenderer::<Hello>::with_props(HelloProps {
|
||||
name
|
||||
});
|
||||
let renderer = ServerRenderer::<Hello>::with_props(HelloProps { name });
|
||||
HttpResponse::Ok().body(renderer.render().await)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
pub mod hello_controller;
|
||||
pub mod hello_controller;
|
||||
pub mod users_controller;
|
||||
|
|
44
src/controllers/users_controller.rs
Normal file
44
src/controllers/users_controller.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use actix_web::{get, web, Error, HttpResponse};
|
||||
use yew::ServerRenderer;
|
||||
|
||||
use crate::{
|
||||
models::user::{NewUser, User},
|
||||
views::components::{
|
||||
user::{UserComponent, UserComponentProps},
|
||||
users::{UsersComponent, UsersComponentProps}
|
||||
},
|
||||
DbPool,
|
||||
};
|
||||
|
||||
#[get("")]
|
||||
async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
|
||||
let users = web::block(move || {
|
||||
let conn = pool.get()?;
|
||||
User::all(&conn)
|
||||
})
|
||||
.await?
|
||||
.map_err(actix_web::error::ErrorInternalServerError)?;
|
||||
|
||||
let renderer =
|
||||
ServerRenderer::<UsersComponent>::with_props(UsersComponentProps { users: users.clone() });
|
||||
Ok(HttpResponse::Ok().body(renderer.render().await))
|
||||
}
|
||||
|
||||
#[get("")]
|
||||
async fn create(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
|
||||
let user = User::new(NewUser {
|
||||
name: "John".to_string(),
|
||||
});
|
||||
|
||||
let u = user.clone();
|
||||
web::block(move || {
|
||||
let conn = pool.get()?;
|
||||
u.insert(&conn)
|
||||
})
|
||||
.await?
|
||||
.map_err(actix_web::error::ErrorInternalServerError)?;
|
||||
|
||||
let renderer =
|
||||
ServerRenderer::<UserComponent>::with_props(UserComponentProps { user: user.clone() });
|
||||
Ok(HttpResponse::Ok().body(renderer.render().await))
|
||||
}
|
34
src/main.rs
34
src/main.rs
|
@ -1,12 +1,38 @@
|
|||
#[macro_use]
|
||||
extern crate diesel; // Required for schema.rs
|
||||
|
||||
pub(self) mod controllers;
|
||||
pub(self) mod models;
|
||||
pub(self) mod schema;
|
||||
pub(self) mod views;
|
||||
|
||||
use actix_web::{App, HttpServer, web};
|
||||
pub(self) type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>;
|
||||
|
||||
use actix_web::{middleware, web, App, HttpServer};
|
||||
use diesel::{
|
||||
r2d2::{self, ConnectionManager},
|
||||
SqliteConnection,
|
||||
};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()>{
|
||||
HttpServer::new(|| {
|
||||
App::new().service(web::scope("/hello").service(controllers::hello_controller::index))
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
// set up database connection pool
|
||||
let conn_spec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
|
||||
let manager = ConnectionManager::<SqliteConnection>::new(conn_spec);
|
||||
let pool = r2d2::Pool::builder()
|
||||
.build(manager)
|
||||
.expect("Failed to create pool.");
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(web::scope("/hello").service(controllers::hello_controller::index))
|
||||
.service(web::scope("/users").service(controllers::users_controller::index))
|
||||
.service(web::scope("/user").service(controllers::users_controller::create))
|
||||
})
|
||||
.bind(("127.0.0.1", 8000))?
|
||||
.run()
|
||||
|
|
3
src/models/mod.rs
Normal file
3
src/models/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub(self) type DbError = Box<dyn std::error::Error + Send + Sync>;
|
||||
|
||||
pub mod user;
|
64
src/models/user.rs
Normal file
64
src/models/user.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::schema::users;
|
||||
|
||||
use super::DbError;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable, AsChangeset, PartialEq)]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NewUser {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new(new_user: NewUser) -> Self {
|
||||
Self {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
name: new_user.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all(conn: &SqliteConnection) -> Result<Vec<Self>, DbError> {
|
||||
users::table.load::<Self>(conn).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn find_by_id(conn: &SqliteConnection, id: String) -> Result<Self, DbError> {
|
||||
users::table
|
||||
.filter(users::id.eq(id))
|
||||
.first::<Self>(conn)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn insert(&self, conn: &SqliteConnection) -> Result<(), DbError> {
|
||||
use crate::schema::users::dsl::*;
|
||||
|
||||
diesel::insert_into(users).values(self).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update(&self, conn: &SqliteConnection) -> Result<(), DbError> {
|
||||
use crate::schema::users::dsl::*;
|
||||
|
||||
diesel::update(users.find(self.id.clone()))
|
||||
.set(self)
|
||||
.execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &SqliteConnection) -> Result<(), DbError> {
|
||||
use crate::schema::users::dsl::*;
|
||||
|
||||
diesel::delete(users.filter(id.eq(self.id.clone()))).execute(conn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
6
src/schema.rs
Normal file
6
src/schema.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
table! {
|
||||
users (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
}
|
||||
}
|
|
@ -1 +1,3 @@
|
|||
pub mod hello;
|
||||
pub mod hello;
|
||||
pub mod user;
|
||||
pub mod users;
|
18
src/views/components/user.rs
Normal file
18
src/views/components/user.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
use crate::models::user::User;
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct UserComponentProps {
|
||||
pub user: User,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn UserComponent(props: &UserComponentProps) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<p>{ props.user.clone().id } </p>
|
||||
<p>{ props.user.clone().name } </p>
|
||||
</div>
|
||||
}
|
||||
}
|
21
src/views/components/users.rs
Normal file
21
src/views/components/users.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
use crate::models::user::User;
|
||||
use crate::views::components::user::UserComponent;
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct UsersComponentProps {
|
||||
pub users: Vec<User>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn UsersComponent(props: &UsersComponentProps) -> Html {
|
||||
let users = props.users.clone().iter().map(|user| html! {
|
||||
<UserComponent user={user.clone()} />
|
||||
}).collect::<Html>();
|
||||
html! {
|
||||
<div>
|
||||
{ users }
|
||||
</div>
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue