类型改为Result
This commit is contained in:
parent
52b8d0a235
commit
499bdfa9fc
|
@ -6,7 +6,9 @@ use crate::repo::pokemon::Repository;
|
|||
|
||||
#[derive(Serialize)]
|
||||
struct Response{
|
||||
message: String,
|
||||
number: u16,
|
||||
name: String,
|
||||
types: Vec<String>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct Request {
|
||||
|
@ -24,10 +26,19 @@ pub fn serve(repo: Arc<dyn Repository>, req: &rouille::Request) -> rouille::Resp
|
|||
},
|
||||
_ => return rouille::Response::from(Status::BadRequest),
|
||||
};
|
||||
// rouille::Response::from(Status::InternalServerError)
|
||||
match create_pokemon::execute(repo, req) {
|
||||
create_pokemon::Response::Ok(number) => rouille::Response::json(&Response{message: number.to_string()}),
|
||||
create_pokemon::Response::BadRequest => rouille::Response::from(Status::BadRequest),
|
||||
create_pokemon::Response::Conflict => rouille::Response::from(Status::Conflict),
|
||||
create_pokemon::Response::Error => rouille::Response::from(Status::InternalServerError),
|
||||
Ok(create_pokemon::Response {
|
||||
number,
|
||||
name,
|
||||
types,
|
||||
}) => rouille::Response::json(&Response{
|
||||
number,
|
||||
name,
|
||||
types,
|
||||
}),
|
||||
Err(create_pokemon::Error::BadRequest) => rouille::Response::from(Status::BadRequest),
|
||||
Err(create_pokemon::Error::Conflict) => rouille::Response::from(Status::Conflict),
|
||||
Err(create_pokemon::Error::Unknown) => rouille::Response::from(Status::InternalServerError),
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
use crate::domain::entity::{PokemonName, PokemonNumber, PokemonTypes};
|
||||
use crate::repo::pokemon::{Insert, Repository};
|
||||
use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes};
|
||||
use crate::repo::pokemon::{InsertError, Repository};
|
||||
|
||||
pub struct Request {
|
||||
pub(crate) number: u16,
|
||||
|
@ -8,14 +8,19 @@ pub struct Request {
|
|||
pub(crate) types: Vec<String>,
|
||||
}
|
||||
|
||||
pub enum Response {
|
||||
Ok(u16),
|
||||
pub enum Error {
|
||||
BadRequest,
|
||||
Conflict,
|
||||
Error,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
pub fn execute(repo: Arc<dyn Repository>, req: Request) -> Response {
|
||||
pub struct Response {
|
||||
pub number: u16,
|
||||
pub name: String,
|
||||
pub types: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn execute(repo: Arc<dyn Repository>, req: Request) -> Result<Response, Error> {
|
||||
println!("execute");
|
||||
match (
|
||||
PokemonNumber::try_from(req.number),
|
||||
|
@ -23,11 +28,19 @@ pub fn execute(repo: Arc<dyn Repository>, req: Request) -> Response {
|
|||
PokemonTypes::try_from(req.types)
|
||||
) {
|
||||
(Ok(number), Ok(name), Ok(types)) => match repo.insert(number, name, types){
|
||||
Insert::Ok(num) => Response::Ok(u16::from(num)),
|
||||
Insert::Conflict => Response::Conflict,
|
||||
Insert::Error => Response::Error,
|
||||
Ok(Pokemon {
|
||||
number,
|
||||
name,
|
||||
types,
|
||||
}) => Ok(Response{
|
||||
number: u16::from(number),
|
||||
name: String::from(name),
|
||||
types: Vec::<String>::from(types),
|
||||
}),
|
||||
Err(InsertError::Conflict) => Err(Error::Conflict),
|
||||
Err(InsertError::Error) => Err(Error::Unknown),
|
||||
},
|
||||
_ => Response::BadRequest,
|
||||
_ => Err(Error::BadRequest),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +50,7 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_should_return_the_pokemon_number_otherwise() {
|
||||
fn it_should_return_an_unknown_error_when_an_unexpected_error_happens(){
|
||||
let mut repo = Arc::new(InMemoryRepository::new());
|
||||
let number = 25;
|
||||
let req = Request {
|
||||
|
@ -47,7 +60,27 @@ mod tests {
|
|||
};
|
||||
let res = execute(repo, req);
|
||||
match res {
|
||||
Response::Ok(num) => assert_eq!(num, number),
|
||||
Err(Error::Unknown) => {},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_return_the_pokemon_number_otherwise() {
|
||||
let repo = Arc::new(InMemoryRepository::new());
|
||||
let num = 25;
|
||||
let req = Request {
|
||||
number: num,
|
||||
name: "Pikachu".to_string(),
|
||||
types: vec!["Electric".to_string(), ],
|
||||
};
|
||||
let res = execute(repo, req);
|
||||
match res {
|
||||
Ok(Response {
|
||||
number,
|
||||
name,
|
||||
types,
|
||||
}) => assert_eq!(number, num),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -55,16 +88,20 @@ mod tests {
|
|||
#[test]
|
||||
fn it_should_return_a_bad_request_error_when_request_is_invalid() {
|
||||
let mut repo = Arc::new(InMemoryRepository::new());
|
||||
let number = 25;
|
||||
let num = 25;
|
||||
let req = Request {
|
||||
number: number,
|
||||
number: num,
|
||||
name: "".to_string(),
|
||||
types: vec!["Electric".to_string(), ],
|
||||
};
|
||||
let res = execute(repo, req);
|
||||
match res {
|
||||
Response::Ok(num) => assert_eq!(num, number),
|
||||
Response::BadRequest => {},
|
||||
Ok(Response{
|
||||
number,
|
||||
name,
|
||||
types,
|
||||
}) => assert_eq!(number, num),
|
||||
Err(Error::BadRequest) => {},
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +120,7 @@ mod tests {
|
|||
};
|
||||
let res = execute(repo, req);
|
||||
match res {
|
||||
Response::Conflict => {},
|
||||
Err(Error::Conflict) => {},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Pokemon {
|
||||
pub number: PokemonNumber,
|
||||
name: PokemonName,
|
||||
types: PokemonTypes,
|
||||
pub name: PokemonName,
|
||||
pub types: PokemonTypes,
|
||||
}
|
||||
|
||||
impl Pokemon {
|
||||
|
@ -36,7 +36,7 @@ impl From<PokemonNumber> for u16 {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PokemonName(String);
|
||||
|
||||
impl TryFrom<String> for PokemonName {
|
||||
|
@ -51,7 +51,13 @@ impl TryFrom<String> for PokemonName {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl From<PokemonName> for String {
|
||||
fn from(value: PokemonName) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PokemonTypes(Vec<PokemonType>);
|
||||
|
||||
impl TryFrom<Vec<String>> for PokemonTypes {
|
||||
|
@ -73,7 +79,26 @@ impl TryFrom<Vec<String>> for PokemonTypes {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl From<PokemonTypes> for Vec<String> {
|
||||
fn from(value: PokemonTypes) -> Self {
|
||||
let mut ts = vec![];
|
||||
for pt in value.0.into_iter() {
|
||||
ts.push(String::from(pt));
|
||||
}
|
||||
ts
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PokemonType> for String {
|
||||
fn from(value: PokemonType) -> Self {
|
||||
String::from(match value {
|
||||
PokemonType::Electric => "Electric",
|
||||
PokemonType::Fire => "Fire",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum PokemonType {
|
||||
Electric,
|
||||
Fire,
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::sync::Mutex;
|
|||
use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes};
|
||||
|
||||
pub trait Repository: Send + Sync {
|
||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert;
|
||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError>;
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct InMemoryRepository {
|
||||
|
@ -17,32 +17,38 @@ impl InMemoryRepository {
|
|||
pokemons
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
pub fn with_error(self) -> Self {
|
||||
Self {
|
||||
error: true,
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Insert {
|
||||
Ok(PokemonNumber),
|
||||
pub enum InsertError {
|
||||
Conflict,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Repository for InMemoryRepository {
|
||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert {
|
||||
fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Result<Pokemon, InsertError> {
|
||||
if self.error {
|
||||
return Insert::Error;
|
||||
return Err(InsertError::Error);
|
||||
}
|
||||
let mut lock = match self.pokemons.lock() {
|
||||
Ok(lock) => lock,
|
||||
_ => return Insert::Error,
|
||||
_ => return Err(InsertError::Error),
|
||||
};
|
||||
|
||||
|
||||
println!("{number:?} {:?}", self.pokemons);
|
||||
if lock.iter().any(|pokemon| pokemon.number == number) {
|
||||
return Insert::Conflict;
|
||||
return Err(InsertError::Conflict);
|
||||
}
|
||||
let number_clone = number.clone();
|
||||
lock.push(Pokemon::new(number_clone, name, types));
|
||||
let pokemon = Pokemon::new(number_clone, name, types);
|
||||
lock.push(pokemon.clone());
|
||||
println!("{number:?} {:?}", self.pokemons);
|
||||
Insert::Ok(number)
|
||||
Ok(pokemon)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue