🔨 Refactors into packages models and dtos

This commit is contained in:
2025-10-05 19:44:31 +02:00
parent 91837d736f
commit cb9cfec119
9 changed files with 130 additions and 78 deletions

View File

@@ -1,29 +1,73 @@
use crate::dtos::TrackerDTO; use crate::dtos::tracker::TrackerDTO;
use crate::models::{AppState, Tracker}; use crate::models::AppState;
use crate::schema::trackers::dsl::trackers; use crate::models::tracker::{NewTracker, Tracker};
use diesel::{QueryDsl, RunQueryDsl, SelectableHelper}; use crate::schema::trackers;
use chrono::Utc;
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl, SelectableHelper};
use rocket::State; use rocket::State;
use rocket::http::Status;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use uuid::Uuid;
#[get("/?<offset>&<limit>")] #[get("/?<offset>&<limit>")]
pub fn index( pub fn index(
offset: Option<i64>, offset: Option<i64>,
limit: Option<i64>, limit: Option<i64>,
data: &State<AppState>, state: &State<AppState>,
) -> Json<Vec<TrackerDTO>> { ) -> Result<Json<Vec<TrackerDTO>>, Status> {
let mut db = data.db.lock().unwrap(); let mut db = state.db.lock().unwrap();
let offset = offset.unwrap_or(0); let offset = offset.unwrap_or(0);
let limit = limit.unwrap_or(10); let limit = limit.unwrap_or(10);
println!("hey"); let results = trackers::dsl::trackers
let results = trackers
.offset(offset) .offset(offset)
.limit(limit) .limit(limit)
.select(Tracker::as_select()) .select(Tracker::as_select())
.load(&mut *db) .load(&mut *db)
.expect("Error loading trackers"); .ok();
println!("hi"); match results {
Json(results.iter().map(TrackerDTO::from).collect()) Some(results) => Ok(Json(results.iter().map(TrackerDTO::from).collect())),
None => Err(Status::InternalServerError),
}
}
#[get("/<id>")]
pub fn get(id: String, state: &State<AppState>) -> Result<Json<TrackerDTO>, Status> {
let mut db = state.db.lock().unwrap();
let id = match Uuid::parse_str(id.as_str()).ok() {
Some(id) => id,
None => return Err(Status::NotFound),
};
let result = trackers::dsl::trackers
.filter(trackers::id.eq(id))
.first::<Tracker>(&mut *db)
.ok();
match result {
Some(tracker) => Ok(Json(TrackerDTO::from(&tracker))),
None => Err(Status::NotFound),
}
}
#[post("/")]
pub fn create(state: &State<AppState>) -> Result<Json<TrackerDTO>, Status> {
let mut db = state.db.lock().unwrap();
let new = NewTracker {
created_at: Utc::now().naive_utc(),
};
let result = diesel::insert_into(trackers::table)
.values(&new)
.returning(Tracker::as_returning())
.get_result(&mut *db)
.ok();
match result {
Some(tracker) => Ok(Json(TrackerDTO::from(&tracker))),
None => Err(Status::InternalServerError),
}
} }

View File

@@ -1,22 +1,6 @@
use chrono::{DateTime, Utc}; use crate::models::hit::Hit;
use crate::models::{Hit, Tracker};
use serde::Serialize; use serde::Serialize;
#[derive(Serialize)]
pub struct TrackerDTO {
pub id: String,
pub created_at: String,
}
impl TrackerDTO {
pub fn from(tracker: &Tracker) -> TrackerDTO {
TrackerDTO {
id: tracker.id.to_string(),
created_at: tracker.created_at.to_string(),
}
}
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct HitDTO { pub struct HitDTO {
pub id: String, pub id: String,

2
src/dtos/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod hit;
pub mod tracker;

17
src/dtos/tracker.rs Normal file
View File

@@ -0,0 +1,17 @@
use crate::models::tracker::Tracker;
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
pub struct TrackerDTO {
pub id: String,
pub created_at: String,
}
impl TrackerDTO {
pub fn from(tracker: &Tracker) -> TrackerDTO {
TrackerDTO {
id: tracker.id.to_string(),
created_at: tracker.created_at.to_string(),
}
}
}

View File

@@ -1,12 +1,10 @@
mod api; mod api;
mod dtos;
mod models; mod models;
mod schema; mod schema;
mod dtos;
use crate::api::tracker; use crate::api::tracker;
use crate::models::Hit; use diesel::{Connection, PgConnection};
use crate::schema::hits::dsl::*;
use diesel::{Connection, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper};
use std::env; use std::env;
#[macro_use] #[macro_use]
@@ -22,19 +20,12 @@ fn rocket() -> _ {
dotenv::dotenv().ok(); dotenv::dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let mut db = PgConnection::establish(&database_url) let db = PgConnection::establish(&database_url)
.expect(&format!("Error connecting to {}", database_url)); .expect(&format!("Error connecting to {}", database_url));
let results = hits
.limit(5)
.select(Hit::as_select())
.load(&mut db)
.expect("Error loading hits");
println!("results: {}", results.len());
let app_data = models::AppState::new(db); let app_data = models::AppState::new(db);
rocket::build() rocket::build()
.manage(app_data) .manage(app_data)
.mount("/", routes![index]) .mount("/", routes![index])
.mount("/tracker", routes![tracker::index]) .mount("/tracker", routes![tracker::index, tracker::get, tracker::create])
} }

View File

@@ -1,36 +0,0 @@
use chrono::NaiveDateTime;
use diesel::{PgConnection, Queryable, Selectable};
use std::sync::{Arc, Mutex};
use uuid::Uuid;
#[derive(Queryable, Selectable, Clone)]
#[diesel(table_name = crate::schema::trackers)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Tracker {
pub id: Uuid,
pub created_at: NaiveDateTime,
}
#[derive(Queryable, Selectable, Clone)]
#[diesel(table_name = crate::schema::hits)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Hit {
pub id: Uuid,
pub tracker_id: Uuid,
pub ip: String,
pub agent: Option<String>,
pub language: Option<String>,
pub created_at: NaiveDateTime,
}
pub struct AppState {
pub db: Arc<Mutex<PgConnection>>,
}
impl AppState {
pub fn new(db: PgConnection) -> Self {
AppState {
db: Arc::new(Mutex::new(db)),
}
}
}

15
src/models/hit.rs Normal file
View File

@@ -0,0 +1,15 @@
use chrono::NaiveDateTime;
use diesel::{Queryable, Selectable};
use uuid::Uuid;
#[derive(Queryable, Selectable, Clone)]
#[diesel(table_name = crate::schema::hits)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Hit {
pub id: Uuid,
pub tracker_id: Uuid,
pub ip: String,
pub agent: Option<String>,
pub language: Option<String>,
pub created_at: NaiveDateTime,
}

17
src/models/mod.rs Normal file
View File

@@ -0,0 +1,17 @@
use diesel::PgConnection;
use std::sync::{Arc, Mutex};
pub mod hit;
pub mod tracker;
pub struct AppState {
pub db: Arc<Mutex<PgConnection>>,
}
impl AppState {
pub fn new(db: PgConnection) -> Self {
AppState {
db: Arc::new(Mutex::new(db)),
}
}
}

18
src/models/tracker.rs Normal file
View File

@@ -0,0 +1,18 @@
use chrono::NaiveDateTime;
use diesel::{Insertable, Queryable, Selectable};
use uuid::Uuid;
#[derive(Queryable, Selectable, Clone)]
#[diesel(table_name = crate::schema::trackers)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct Tracker {
pub id: Uuid,
pub created_at: NaiveDateTime,
}
#[derive(Insertable)]
#[diesel(table_name = crate::schema::trackers)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct NewTracker {
pub created_at: NaiveDateTime,
}