fix create teacher route, refactoring route function

This commit is contained in:
Akhmedov Khadgimurad
2025-11-19 14:42:56 +03:00
parent e7f20a4d82
commit 8ec1f3a17f
8 changed files with 50 additions and 44 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
*.db

View File

@ -1,3 +1 @@
-- Add migration script here
drop table "patients"; drop table "patients";

View File

@ -1,5 +1,3 @@
-- Add migration script here
create table "patients" ( create table "patients" (
"id" INTEGER PRIMARY KEY, "id" INTEGER PRIMARY KEY,
"full_name" TEXT NOT NULL, "full_name" TEXT NOT NULL,

BIN
mydb.db

Binary file not shown.

View File

@ -1,3 +1,9 @@
insert into patients ("full_name", "phone") insert into patients(
values($1,$2) "full_name",
returning "id"; "phone"
)
values($1, $2)
returning
"id",
"full_name" as "full_name!",
"phone" as "phone!"

View File

@ -1,12 +1,11 @@
use axum::{ use axum::{
debug_handler, Router, debug_handler,
extract::{Json, Path, State}, extract::{Json, Path, State},
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
}; };
use models::Patient; use models::Patient;
use sqlx::{query_file, query_file_as, query_file_scalar}; use sqlx::{query_file, query_file_as};
use tracing::info;
use utoipa::OpenApi; use utoipa::OpenApi;
use utoipa_axum::{router::OpenApiRouter, routes}; use utoipa_axum::{router::OpenApiRouter, routes};
@ -24,26 +23,25 @@ pub mod schemas;
#[derive(OpenApi)] #[derive(OpenApi)]
struct Api; struct Api;
pub async fn router(state: AppState) { pub fn router(state: AppState) -> Router {
let addr = "0.0.0.0:3000";
tracing_subscriber::fmt::init();
let (router, docs) = OpenApiRouter::with_openapi(Api::openapi()) let (router, docs) = OpenApiRouter::with_openapi(Api::openapi())
.routes(routes!(get_openapi)) .nest(
.routes(routes!(create_patient)) "/api/patients/",
.routes(routes!(get_all)) OpenApiRouter::new()
.routes(routes!(update_patient_by_id)) .routes(routes!(create_patient, get_all))
.routes(routes!(delete_patient_by_id)) .routes(routes!(
.routes(routes!(get_patient_by_id)) update_patient_by_id,
delete_patient_by_id,
get_patient_by_id
)),
)
.with_state(state) .with_state(state)
.split_for_parts(); .split_for_parts();
let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); route_docs(router, docs)
info!("Listening in {:?}", listener.local_addr());
let router = route_docs(router, docs);
axum::serve(listener, router).await.unwrap();
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(get, path = "/api/patients", description="Get all patients", responses((status = OK, body = Patient)))] #[utoipa::path(get, path = "/", description="Get all patients", responses((status = OK, body = Patient)))]
async fn get_all(State(state): State<AppState>) -> Json<Vec<Patient>> { async fn get_all(State(state): State<AppState>) -> Json<Vec<Patient>> {
let patients = query_file_as!(Patient, "queries/get_all.sql") let patients = query_file_as!(Patient, "queries/get_all.sql")
.fetch_all(&state.pool) .fetch_all(&state.pool)
@ -53,7 +51,7 @@ async fn get_all(State(state): State<AppState>) -> Json<Vec<Patient>> {
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(get, path = "/api/patients/{id}", description="Get all patients", responses((status = OK, body = Patient)))] #[utoipa::path(get, path = "/{id}", description="Get all patients", responses((status = OK, body = Patient)))]
async fn get_patient_by_id( async fn get_patient_by_id(
State(state): State<AppState>, State(state): State<AppState>,
Path(path): Path<PathParams>, Path(path): Path<PathParams>,
@ -69,18 +67,13 @@ async fn get_patient_by_id(
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(get, path = "/api/openapi.json", description = "Get openapi.json file", responses((status = OK)))] #[utoipa::path(post, path = "/", description = "Create a new patient", responses((status = OK)))]
async fn get_openapi() -> impl IntoResponse {
axum::http::StatusCode::NOT_IMPLEMENTED
}
#[debug_handler]
#[utoipa::path(post, path = "/api/patients", description = "Create a new patient", responses((status = OK)))]
async fn create_patient( async fn create_patient(
State(state): State<AppState>, State(state): State<AppState>,
Json(patient): Json<CreatePatient>, Json(patient): Json<CreatePatient>,
) -> Json<i64> { ) -> Json<Patient> {
let new_patient_id = query_file_scalar!( let patient = query_file_as!(
Patient,
"queries/create_patient.sql", "queries/create_patient.sql",
patient.full_name, patient.full_name,
patient.phone patient.phone
@ -88,11 +81,12 @@ async fn create_patient(
.fetch_one(&state.pool) .fetch_one(&state.pool)
.await .await
.expect("Could not create new patient"); .expect("Could not create new patient");
Json(new_patient_id)
Json(patient)
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(post, path = "/api/patients/{id}", description = "Update patient by ID", responses((status = OK)))] #[utoipa::path(post, path = "/{id}", description = "Update patient by ID", responses((status = OK)))]
async fn update_patient_by_id( async fn update_patient_by_id(
State(state): State<AppState>, State(state): State<AppState>,
Path(path): Path<PathParams>, Path(path): Path<PathParams>,
@ -111,7 +105,7 @@ async fn update_patient_by_id(
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(delete, path = "/api/patients/{id}", description = "Delete patient by ID", responses((status = OK)))] #[utoipa::path(delete, path = "/{id}", description = "Delete patient by ID", responses((status = OK)))]
async fn delete_patient_by_id( async fn delete_patient_by_id(
State(state): State<AppState>, State(state): State<AppState>,
Path(path): Path<PathParams>, Path(path): Path<PathParams>,

View File

@ -1,16 +1,25 @@
use hospital_server::app_state::AppState; use hospital_server::app_state::AppState;
use hospital_server::router; use hospital_server::router;
use sqlx::SqlitePool; use sqlx::SqlitePool;
use tracing::info;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let _ = dotenvy::dotenv(); let _ = dotenvy::dotenv();
tracing_subscriber::fmt::init();
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL is not set"); let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL is not set");
let pool = SqlitePool::connect(&db_url) let pool = SqlitePool::connect(&db_url)
.await .await
.expect("Cannot connect to db"); .expect("Cannot connect to db");
let state = AppState { pool: pool }; sqlx::migrate!().run(&pool).await.unwrap();
sqlx::migrate!().run(&state.pool).await.unwrap();
router(state).await; let state = AppState { pool };
let router = router(state);
let addr = "0.0.0.0:3000";
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
info!("Listening in {:?}", listener.local_addr());
axum::serve(listener, router).await.unwrap();
} }

View File

@ -1,9 +1,9 @@
use axum::Router; use axum::{Router, routing::get};
use utoipa::openapi::OpenApi; use utoipa::openapi::OpenApi;
use utoipa_scalar::{Scalar, Servable}; use utoipa_scalar::{Scalar, Servable};
struct ApiDocs;
pub fn route_docs(router: Router, docs: OpenApi) -> Router { pub fn route_docs(router: Router, docs: OpenApi) -> Router {
router.merge(Scalar::with_url("/", docs)) router
.merge(Scalar::with_url("/", docs.clone()))
.route("/docs/openapi.json", get(docs.to_json().expect("serializing OpenAPI")))
} }