124 lines
3.5 KiB
Rust
124 lines
3.5 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 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<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::*;
|
|
|
|
match ingredients.filter(alias.like(name))
|
|
.first(conn)
|
|
{
|
|
Ok(ingdt) => Some(ingdt),
|
|
Err(_) => None,
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|