查询列表
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 health;
|
||||||
mod create_pokemon;
|
mod create_pokemon;
|
||||||
|
mod fetch_all_pokemons;
|
||||||
|
|
||||||
|
|
||||||
pub fn serve(url: &str, repo: Arc<dyn Repository>) {
|
pub fn serve(url: &str, repo: Arc<dyn Repository>) {
|
||||||
|
@ -14,6 +15,9 @@ pub fn serve(url: &str, repo: Arc<dyn Repository>) {
|
||||||
},
|
},
|
||||||
(POST)(/) => {
|
(POST)(/) => {
|
||||||
create_pokemon::serve(repo.clone(), req)
|
create_pokemon::serve(repo.clone(), req)
|
||||||
|
},
|
||||||
|
(GET)(/) => {
|
||||||
|
fetch_all_pokemons::serve(repo.clone())
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
rouille::Response::from(rouille::Response::empty_404())
|
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);
|
pub struct PokemonNumber(u16);
|
||||||
|
|
||||||
impl TryFrom<u16> for PokemonNumber {
|
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 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 {
|
pub trait Repository: Send + Sync {
|
||||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError>;
|
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError>;
|
||||||
|
fn fetch_all(&self) -> Result<Vec<Pokemon>, FetchAllError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InMemoryRepository {
|
pub struct InMemoryRepository {
|
||||||
error: bool,
|
error: bool,
|
||||||
|
@ -31,6 +33,10 @@ pub enum InsertError {
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum FetchAllError {
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
impl Repository for InMemoryRepository {
|
impl Repository for InMemoryRepository {
|
||||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError> {
|
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError> {
|
||||||
if self.error {
|
if self.error {
|
||||||
|
@ -51,4 +57,16 @@ impl Repository for InMemoryRepository {
|
||||||
println!("{number:?} {:?}", self.pokemons);
|
println!("{number:?} {:?}", self.pokemons);
|
||||||
Ok(pokemon)
|
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