Initial model + some various changes
This commit is contained in:
parent
a080d19cb9
commit
108476e355
17 changed files with 1070 additions and 1286 deletions
|
|
@ -1,3 +1,4 @@
|
|||
pub static FILE_CONF: &str = "conf.ron";
|
||||
pub static DB_DIRECTORY: &str = "data";
|
||||
pub static DB_FILENAME: &str = "recipes.sqlite";
|
||||
pub const FILE_CONF: &str = "conf.ron";
|
||||
pub const DB_DIRECTORY: &str = "data";
|
||||
pub const DB_FILENAME: &str = "data/recipes.sqlite";
|
||||
pub const SQL_FILENAME: &str = "sql/version_{VERSION}.sql";
|
||||
|
|
@ -1,27 +1,24 @@
|
|||
use std::path::Path;
|
||||
use std::fs;
|
||||
|
||||
//use rusqlite::types::ToSql;
|
||||
//use rusqlite::{Connection, Result, NO_PARAMS};
|
||||
|
||||
//extern crate r2d2;
|
||||
//extern crate r2d2_sqlite;
|
||||
//extern crate rusqlite;
|
||||
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use r2d2::Pool;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DbError {
|
||||
SqliteError(rusqlite::Error),
|
||||
R2d2Error(r2d2::Error),
|
||||
UnsupportedVersion(i32),
|
||||
}
|
||||
use crate::consts::SQL_FILENAME;
|
||||
|
||||
use super::consts;
|
||||
|
||||
use std::{fs::{self, File}, path::Path, io::Read};
|
||||
|
||||
//use rusqlite::types::ToSql;
|
||||
//use rusqlite::{Connection, Result, NO_PARAMS};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
|
||||
const CURRENT_DB_VERSION: u32 = 1;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DBError {
|
||||
SqliteError(rusqlite::Error),
|
||||
R2d2Error(r2d2::Error),
|
||||
UnsupportedVersion(u32),
|
||||
Other(String),
|
||||
}
|
||||
|
||||
pub struct Connection {
|
||||
//con: rusqlite::Connection
|
||||
pool: Pool<SqliteConnectionManager>
|
||||
|
|
@ -32,20 +29,20 @@ pub struct Recipe {
|
|||
pub id: i32,
|
||||
}
|
||||
|
||||
impl std::convert::From<rusqlite::Error> for DbError {
|
||||
impl std::convert::From<rusqlite::Error> for DBError {
|
||||
fn from(error: rusqlite::Error) -> Self {
|
||||
DbError::SqliteError(error)
|
||||
DBError::SqliteError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<r2d2::Error> for DbError {
|
||||
impl std::convert::From<r2d2::Error> for DBError {
|
||||
fn from(error: r2d2::Error) -> Self {
|
||||
DbError::R2d2Error(error)
|
||||
DBError::R2d2Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
pub fn new() -> Result<Connection, DbError> {
|
||||
pub fn new() -> Result<Connection, DBError> {
|
||||
|
||||
let data_dir = Path::new(consts::DB_DIRECTORY);
|
||||
|
||||
|
|
@ -53,7 +50,7 @@ impl Connection {
|
|||
fs::DirBuilder::new().create(data_dir).unwrap();
|
||||
}
|
||||
|
||||
let manager = SqliteConnectionManager::file("file.db");
|
||||
let manager = SqliteConnectionManager::file(consts::DB_FILENAME);
|
||||
let pool = r2d2::Pool::new(manager).unwrap();
|
||||
|
||||
let connection = Connection { pool };
|
||||
|
|
@ -65,7 +62,7 @@ impl Connection {
|
|||
* Called after the connection has been established for creating or updating the database.
|
||||
* The 'Version' table tracks the current state of the database.
|
||||
*/
|
||||
fn create_or_update(self: &Self) -> Result<(), DbError> {
|
||||
fn create_or_update(self: &Self) -> Result<(), DBError> {
|
||||
// let connection = Connection::new();
|
||||
// let mut stmt = connection.sqlite_con.prepare("SELECT * FROM versions ORDER BY date").unwrap();
|
||||
// let mut stmt = connection.sqlite_con.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='versions'").unwrap();
|
||||
|
|
@ -74,13 +71,14 @@ impl Connection {
|
|||
let mut con = self.pool.get()?;
|
||||
let tx = con.transaction()?;
|
||||
|
||||
// Version 0 corresponds to an empty database.
|
||||
let mut version = {
|
||||
match tx.query_row(
|
||||
"SELECT [name] FROM [sqlite_master] WHERE [type] = 'table' AND [name] = 'Version'",
|
||||
rusqlite::NO_PARAMS,
|
||||
[],
|
||||
|row| row.get::<usize, String>(0)
|
||||
) {
|
||||
Ok(_) => tx.query_row("SELECT [version] FROM [Version]", rusqlite::NO_PARAMS, |row| row.get(0)).unwrap_or_default(),
|
||||
Ok(_) => tx.query_row("SELECT [version] FROM [Version]", [], |row| row.get(0)).unwrap_or_default(),
|
||||
Err(_) => 0
|
||||
}
|
||||
};
|
||||
|
|
@ -94,49 +92,45 @@ impl Connection {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_to_next_version(version: i32, tx: &rusqlite::Transaction) -> Result<bool, DbError> {
|
||||
match version {
|
||||
0 => {
|
||||
println!("Update to version 1...");
|
||||
fn update_to_next_version(current_version: u32, tx: &rusqlite::Transaction) -> Result<bool, DBError> {
|
||||
let next_version = current_version + 1;
|
||||
|
||||
// Initial structure.
|
||||
tx.execute_batch(
|
||||
"
|
||||
CREATE TABLE [Version] (
|
||||
[id] INTEGER PRIMARY KEY,
|
||||
[version] INTEGER NOT NULL UNIQUE,
|
||||
[datetime] INTEGER DATETIME
|
||||
);
|
||||
if next_version <= CURRENT_DB_VERSION {
|
||||
println!("Update to version {}...", next_version);
|
||||
}
|
||||
|
||||
CREATE TABLE [Recipe] (
|
||||
[id] INTEGER PRIMARY KEY,
|
||||
[title] INTEGER NOT NULL,
|
||||
[description] INTEGER DATETIME
|
||||
);
|
||||
"
|
||||
)?;
|
||||
fn ok(updated: bool) -> Result<bool, DBError> {
|
||||
if updated {
|
||||
println!("Version updated");
|
||||
}
|
||||
Ok(updated)
|
||||
}
|
||||
|
||||
/*
|
||||
tx.execute(
|
||||
"
|
||||
INSERT INTO Version
|
||||
",
|
||||
rusqlite::NO_PARAMS
|
||||
);*/
|
||||
match next_version {
|
||||
1 => {
|
||||
tx.execute_batch(&load_sql_file(next_version)?)?;
|
||||
|
||||
Ok(true)
|
||||
ok(true)
|
||||
}
|
||||
|
||||
// Current version.
|
||||
1 =>
|
||||
Ok(false),
|
||||
// Version 1 doesn't exist yet.
|
||||
2 =>
|
||||
ok(false),
|
||||
|
||||
v =>
|
||||
Err(DbError::UnsupportedVersion(v)),
|
||||
Err(DBError::UnsupportedVersion(v)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_recipes() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn load_sql_file(version: u32) -> Result<String, DBError> {
|
||||
let sql_file = SQL_FILENAME.replace("{VERSION}", &version.to_string());
|
||||
let mut file = File::open(&sql_file).map_err(|err| DBError::Other(format!("Cannot open SQL file ({}): {}", &sql_file, err.to_string())))?;
|
||||
let mut sql = String::new();
|
||||
file.read_to_string(&mut sql).map_err(|err| DBError::Other(format!("Cannot read SQL file ({}) : {}", &sql_file, err.to_string())))?;
|
||||
Ok(sql)
|
||||
}
|
||||
|
|
@ -4,14 +4,14 @@ use std::{fs::File, env::args};
|
|||
use actix_files as fs;
|
||||
use actix_web::{get, web, Responder, middleware, App, HttpServer, HttpResponse, HttpRequest, web::Query};
|
||||
|
||||
use askama::Template;
|
||||
use listenfd::ListenFd;
|
||||
use askama_actix::Template;
|
||||
use ron::de::from_reader;
|
||||
use serde::Deserialize;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
mod consts;
|
||||
mod model;
|
||||
mod db;
|
||||
|
||||
#[derive(Template)]
|
||||
|
|
@ -53,10 +53,13 @@ fn get_exe_name() -> String {
|
|||
first_arg[first_arg.rfind(sep).unwrap()+1..].to_string()
|
||||
}
|
||||
|
||||
#[actix_rt::main]
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
if process_args() { return Ok(()) }
|
||||
|
||||
std::env::set_var("RUST_LOG", "actix_web=debug");
|
||||
env_logger::init();
|
||||
|
||||
println!("Starting Recipes as web server...");
|
||||
|
||||
let config: Config = {
|
||||
|
|
@ -73,11 +76,11 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
std::env::set_var("RUST_LOG", "actix_web=info");
|
||||
|
||||
let mut listenfd = ListenFd::from_env();
|
||||
let mut server =
|
||||
HttpServer::new(
|
||||
|| {
|
||||
App::new()
|
||||
.wrap(middleware::Logger::default())
|
||||
.wrap(middleware::Compress::default())
|
||||
.service(home_page)
|
||||
.service(view_page)
|
||||
|
|
@ -85,12 +88,7 @@ async fn main() -> std::io::Result<()> {
|
|||
}
|
||||
);
|
||||
|
||||
server =
|
||||
if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
|
||||
server.listen(l).unwrap()
|
||||
} else {
|
||||
server.bind(&format!("0.0.0.0:{}", config.port)).unwrap()
|
||||
};
|
||||
server = server.bind(&format!("0.0.0.0:{}", config.port)).unwrap();
|
||||
|
||||
server.run().await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
struct Recipe {
|
||||
ingredients: Vec<Ingredient>,
|
||||
process: Vec<Group>,
|
||||
title: String,
|
||||
estimate_time: Option<i32>, // [min].
|
||||
difficulty: Option<Difficulty>,
|
||||
|
||||
//ingredients: Vec<Ingredient>, // For four people.
|
||||
process: Vec<Group>,
|
||||
}
|
||||
|
||||
struct Ingredient {
|
||||
quantity: Quantity,
|
||||
quantity: Option<Quantity>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
|
|
@ -12,15 +16,16 @@ struct Quantity {
|
|||
value: f32,
|
||||
unit: String,
|
||||
}
|
||||
|
||||
struct Group {
|
||||
name: String,
|
||||
name: Option<String>,
|
||||
steps: Vec<Step>,
|
||||
}
|
||||
|
||||
struct Step {
|
||||
action: String,
|
||||
input: Vec<StepInput>,
|
||||
output: Vec<IntermediateSubstance>,
|
||||
action: String,
|
||||
input: Vec<StepInput>,
|
||||
output: Vec<IntermediateSubstance>,
|
||||
}
|
||||
|
||||
struct IntermediateSubstance {
|
||||
|
|
@ -30,5 +35,12 @@ struct IntermediateSubstance {
|
|||
|
||||
enum StepInput {
|
||||
Ingredient(Ingredient),
|
||||
IntermediateSubstance,
|
||||
}
|
||||
IntermediateSubstance(IntermediateSubstance),
|
||||
}
|
||||
|
||||
enum Difficulty {
|
||||
Unknown,
|
||||
Easy,
|
||||
Medium,
|
||||
Hard,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue