use super::schema::recipes; use super::schema::ingredients; use super::diesel::prelude::*; pub mod fields { use diesel::{ backend::Backend, sql_types::*, deserialize::{self, FromSql}, serialize::{self, Output, ToSql}, }; use std::io::Write; /// All recipes have a single associated category /// representing the main use of the resulting preparation. /// /// It is stored as Integer #[derive(Debug, Copy, Clone, FromSqlRow, AsExpression)] #[sql_type = "SmallInt"] pub enum RecipeCategory { Breakfast = 0, Starter = 1, MainCourse = 2, Dessert = 3 } impl RecipeCategory { pub fn id(&self) -> i16 { *self as i16 } pub fn name(&self) -> &str { match *self { RecipeCategory::Breakfast => "Petit-déjeuner", RecipeCategory::Starter => "Entrée", RecipeCategory::MainCourse => "Plat principal", RecipeCategory::Dessert => "Dessert" } } pub fn all() -> [Self; 4] { [RecipeCategory::Breakfast, RecipeCategory::Starter, RecipeCategory::MainCourse, RecipeCategory::Dessert] } pub fn from_id(id: i16) -> Option { match id { 0 => Some(RecipeCategory::Breakfast), 1 => Some(RecipeCategory::Starter), 2 => Some(RecipeCategory::MainCourse), 3 => Some(RecipeCategory::Dessert), _ => None, } } } impl FromSql for RecipeCategory where i16: FromSql { fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result { let v = i16::from_sql(bytes)?; if let Some(result) = RecipeCategory::from_id(v){ Ok(result) } else { Err("Invalid RecipeCategory id".into()) } } } impl ToSql for RecipeCategory where i16: ToSql{ fn to_sql(&self, out: &mut Output) -> serialize::Result { i16::to_sql(&(*self as i16), out) } } } /// Data for a recipe stored in DB #[derive(Debug, Clone, Queryable)] pub struct Recipe { pub id: i32, pub title: String, pub category: fields::RecipeCategory, pub ingredients: String, pub preparation: String, } #[derive(Insertable, Debug)] #[table_name="recipes"] pub struct NewRecipe<'a> { pub title: &'a str, pub category: fields::RecipeCategory, pub ingredients: &'a str, pub preparation: &'a str, } impl<'a> NewRecipe<'a> { pub fn new(title: &'a str, category: fields::RecipeCategory, ingredients: &'a str, preparation: &'a str) -> Self { NewRecipe{ title, category, ingredients, preparation, } } pub fn insert(self, conn: &SqliteConnection) -> Result { diesel::insert_into(recipes::table) .values(&self) .execute(conn) .expect("Error inserting recipe"); Ok(self) } } #[derive(Queryable)] pub struct Ingredient { pub id: i32, pub alias: String, } #[derive(Insertable)] #[table_name="ingredients"] pub struct NewIngredient<'a> { pub alias: &'a str, }