查询列表

This commit is contained in:
Jeremy Yin 2023-07-03 22:43:56 +08:00
parent ede5b7074e
commit db75ec502d
6 changed files with 118 additions and 2 deletions

View File

@ -0,0 +1,28 @@
use std::sync::Arc;
use serde::Serialize;
use crate::api::Status;
use crate::domain::fetch_all_pokemons;
use crate::repo::pokemon::Repository;
#[derive(Serialize)]
struct Response {
number: u16,
name: String,
types: Vec<String>,
}
pub fn serve(repo: Arc<dyn Repository>) -> rouille::Response {
match fetch_all_pokemons::execute(repo) {
Ok(res) => rouille::Response::json(
&res.into_iter().map(|p| Response {
number: p.number,
name: p.name,
types: p.types,
}).collect::<Vec<Response>>(),
),
Err(fetch_all_pokemons::Error::Unknown) => {
rouille::Response::from(Status::InternalServerError)
}
}
}

View File

@ -4,6 +4,7 @@ use crate::repo::pokemon::Repository;
mod health;
mod create_pokemon;
mod fetch_all_pokemons;
pub fn serve(url: &str, repo: Arc<dyn Repository>) {
@ -14,6 +15,9 @@ pub fn serve(url: &str, repo: Arc<dyn Repository>) {
},
(POST)(/) => {
create_pokemon::serve(repo.clone(), req)
},
(GET)(/) => {
fetch_all_pokemons::serve(repo.clone())
},
_ => {
rouille::Response::from(rouille::Response::empty_404())

View File

@ -15,7 +15,7 @@ impl Pokemon {
}
}
#[derive(Debug,PartialOrd, PartialEq, Copy, Clone)]
#[derive(Debug,PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
pub struct PokemonNumber(u16);
impl TryFrom<u16> for PokemonNumber {

View File

@ -0,0 +1,65 @@
use std::sync::Arc;
use crate::domain::create_pokemon::Response;
use crate::repo::pokemon::{FetchAllError, Repository};
pub enum Error {
Unknown,
}
pub fn execute(repo: Arc<dyn Repository>) -> Result<Vec<Response>, Error>{
match repo.fetch_all() {
Ok(pokemons) => Ok(pokemons.into_iter().map(|p| Response {
number: u16::from(p.number),
name: String::from(p.name),
types: Vec::<String>::from(p.types),
}).collect()),
Err(FetchAllError::Unknown) => Err(Error::Unknown),
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use crate::domain::entity::{PokemonName, PokemonNumber, PokemonTypes};
use crate::domain::fetch_all_pokemons::{Error};
use crate::domain::fetch_all_pokemons::execute;
use crate::repo::pokemon::{InMemoryRepository, Repository};
#[test]
fn it_should_return_an_unkown_error_when_an_unexpected_error_happens() {
let repo = Arc::new(InMemoryRepository::new().with_error());
let res = execute(repo);
match res {
Err(Error::Unknown) => {},
_ => unreachable!(),
}
}
#[test]
fn it_should_return_all_pokemons_ordered_by_increasing_number_otherwise() {
let repo = Arc::new(InMemoryRepository::new());
repo.insert(
PokemonNumber::pikachu(),
PokemonName::pikachu(),
PokemonTypes::pikachu(),
).ok();
repo.insert(
PokemonNumber::charmander(),
PokemonName::charmander(),
PokemonTypes::charmander(),
).ok();
let res = execute(repo);
match res {
Ok(res) => {
assert_eq!(res[0].number, u16::from(PokemonNumber::charmander()));
assert_eq!(res[0].name, String::from(PokemonName::charmander()));
assert_eq!(res[0].types, Vec::<String>::from(PokemonTypes::charmander()));
assert_eq!(res[1].number, u16::from(PokemonNumber::pikachu()));
assert_eq!(res[1].name, String::from(PokemonName::pikachu()));
assert_eq!(res[1].types, Vec::<String>::from(PokemonTypes::pikachu()));
},
Err(Error::Unknown) => {}
}
}
}

View File

@ -1,2 +1,3 @@
pub mod create_pokemon;
pub mod entity;
pub mod entity;
pub mod fetch_all_pokemons;

View File

@ -3,7 +3,9 @@ use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes};
pub trait Repository: Send + Sync {
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError>;
fn fetch_all(&self) -> Result<Vec<Pokemon>, FetchAllError>;
}
#[derive(Debug)]
pub struct InMemoryRepository {
error: bool,
@ -31,6 +33,10 @@ pub enum InsertError {
Error,
}
pub enum FetchAllError {
Unknown,
}
impl Repository for InMemoryRepository {
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError> {
if self.error {
@ -51,4 +57,16 @@ impl Repository for InMemoryRepository {
println!("{number:?} {:?}", self.pokemons);
Ok(pokemon)
}
fn fetch_all(&self) -> Result<Vec<Pokemon>, FetchAllError> {
if self.error {
return Err(FetchAllError::Unknown);
}
let lock = match self.pokemons.lock() {
Ok(lock) => lock,
Err(_) => return Err(FetchAllError::Unknown),
};
let mut pokemons = lock.to_vec();
pokemons.sort_by(|a, b| a.number.cmp(&b.number));
Ok(pokemons)
}
}