Files
CookAssistant/cookbook/src/lib.rs
2019-02-16 15:13:33 +01:00

130 lines
3.7 KiB
Rust

#[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<Recipe> {
use self::schema::recipes::dsl::*;
recipes.load::<Recipe>(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 fn get(conn: &SqliteConnection, recipe_id: i32) -> Option<Recipe> {
use self::schema::recipes::dsl::*;
recipes.filter(id.eq(recipe_id))
.first(conn)
.ok()
}
}
pub mod ingredients {
pub use crate::models::{
Ingredient,
NewIngredient,
fields::{IngredientId, IngredientList},
};
use super::{SqliteConnection, schema};
use super::diesel::prelude::*;
/// A wrapper of [`IngredientList`] with DB connection capacity.
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<i32,String> {
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<Ingredient,String> {
use self::schema::ingredients::dsl::*;
ingredients.filter(id.eq(ingdt_id))
.first::<Ingredient>(conn)
.map_err(|e| format!("Could not retrieve : {}", e))
}
fn find(conn: &SqliteConnection, name: &str) -> Option<Ingredient> {
use self::schema::ingredients::dsl::*;
ingredients.filter(alias.like(name))
.first(conn)
.ok()
}
fn create(conn: &SqliteConnection, name: &str) -> Result<i32,String> {
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::<Ingredient>(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);
}
}