#[macro_use] extern crate diesel; extern crate dotenv; mod schema; mod models; mod importer; use diesel::prelude::*; use dotenv::dotenv; use std::env; pub fn establish_connection() -> SqliteConnection { dotenv().ok(); let db_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set !"); SqliteConnection::establish(&db_url) .expect(&format!("Error connecting to {}", db_url)) } pub mod recipes { pub use crate::models::{Recipe, NewRecipe, fields::RecipeCategory}; use super::{SqliteConnection, schema}; use super::diesel::prelude::*; /// Loads all recipes from database pub fn load_all(conn: &SqliteConnection) -> Vec { use self::schema::recipes::dsl::*; recipes.load::(conn) .expect("Error loading recipe's list") } pub fn delete(conn: &SqliteConnection, recipe_id: i32) -> bool { use self::schema::recipes::dsl::*; diesel::delete(recipes.filter(id.eq(recipe_id))) .execute(conn) .is_ok() } } pub mod ingredients { pub use crate::models::{ Ingredient, NewIngredient, fields::{IngredientId, IngredientList}, }; use super::{SqliteConnection, schema}; use super::diesel::prelude::*; pub struct IngredientListManager<'a>(&'a SqliteConnection, IngredientList); impl<'a> IngredientListManager<'a> { pub fn display_lines(&self) -> String { use self::get; let mut repr = String::new(); for id in self.1.iter() { let ingdt = get(self.0, id).expect("Database integrity error"); repr.push_str(&format!("{}\n", ingdt.alias)); } repr } } impl<'a> IngredientList { pub fn into_manager(self, conn: &'a SqliteConnection) -> IngredientListManager<'a> { IngredientListManager(conn, self) } } /// Returns the id of the ingredient identifiable by `name: &str` /// If the ingredient does not yet exists, it is inserted in database. pub fn get_id_or_create(conn: &SqliteConnection, name: &str) -> Result { if let Some(ingdt) = find(conn, name) { return Ok(ingdt.id); } else { return create(conn, name); } } pub fn get(conn: &SqliteConnection, ingdt_id: &IngredientId) -> Result { use self::schema::ingredients::dsl::*; ingredients.filter(id.eq(ingdt_id)) .first::(conn) .map_err(|e| format!("Could not retrieve : {}", e)) } fn find(conn: &SqliteConnection, name: &str) -> Option { use self::schema::ingredients::dsl::*; match ingredients.filter(alias.like(name)) .first(conn) { Ok(ingdt) => Some(ingdt), Err(_) => None, } } fn create(conn: &SqliteConnection, name: &str) -> Result { use self::schema::ingredients::dsl::*; let _ = diesel::insert_into(ingredients) .values(&NewIngredient { alias: name }) .execute(conn) .map_err(|e| format!("Error inserting ingredient ! {:?}", e))?; let inserted = ingredients .order(id.desc()) .first::(conn) .map_err(|e| format!("No ingredient at all ! {:?}", e))?; Ok(inserted.id) } } #[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }