查询列表
This commit is contained in:
parent
ede5b7074e
commit
db75ec502d
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) => {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod create_pokemon;
|
||||
pub mod entity;
|
||||
pub mod entity;
|
||||
pub mod fetch_all_pokemons;
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue