diff options
| author | Melody Horn / boringcactus <melody@boringcactus.com> | 2021-06-16 12:36:47 -0600 | 
|---|---|---|
| committer | Melody Horn / boringcactus <melody@boringcactus.com> | 2021-06-16 12:36:47 -0600 | 
| commit | 685b47247aad71468f190c42929ca6f0dce843fa (patch) | |
| tree | 7adf64a4c00b9ca8893fab26367ec01a30e24ad9 | |
| parent | 92bf14bb7cc0c10f67a9a67e7512138c15db6ec0 (diff) | |
| download | tosin-685b47247aad71468f190c42929ca6f0dce843fa.tar.gz tosin-685b47247aad71468f190c42929ca6f0dce843fa.zip | |
make database backends generic
| -rw-r--r-- | examples/tutorial01/main.rs | 3 | ||||
| -rw-r--r-- | examples/tutorial02/main.rs | 3 | ||||
| -rw-r--r-- | examples/tutorial02/polls/migrations/mod.rs | 3 | ||||
| -rw-r--r-- | examples/tutorial02/polls/mod.rs | 3 | ||||
| -rw-r--r-- | src/bin/tosin-admin.rs | 3 | ||||
| -rw-r--r-- | src/cli/migrate.rs | 19 | ||||
| -rw-r--r-- | src/cli/mod.rs | 9 | ||||
| -rw-r--r-- | src/cli/run_server.rs | 4 | ||||
| -rw-r--r-- | src/db/backend.rs | 19 | ||||
| -rw-r--r-- | src/settings.rs | 10 | ||||
| -rw-r--r-- | tests/tutorial/mod.rs | 54 | ||||
| -rw-r--r-- | tests/tutorial_steps.rs | 7 | 
12 files changed, 104 insertions, 33 deletions
| diff --git a/examples/tutorial01/main.rs b/examples/tutorial01/main.rs index 0fb087d..7426ab7 100644 --- a/examples/tutorial01/main.rs +++ b/examples/tutorial01/main.rs @@ -1,5 +1,6 @@  use tosin::Settings;  use tosin::contrib::admin; +use tosin::db::backend::Connectable;  use tosin::urls::{UrlMap, url_map};  mod polls; @@ -11,7 +12,7 @@ fn urls() -> UrlMap {      }  } -fn settings() -> Settings { +fn settings() -> Settings<impl Connectable> {      Settings {          ..Settings::default()      } diff --git a/examples/tutorial02/main.rs b/examples/tutorial02/main.rs index eeb7524..0f8dc11 100644 --- a/examples/tutorial02/main.rs +++ b/examples/tutorial02/main.rs @@ -1,5 +1,6 @@  use tosin::Settings;  use tosin::contrib::admin; +use tosin::db::backend::Connectable;  use tosin::urls::{UrlMap, url_map};  mod polls; @@ -11,7 +12,7 @@ fn urls() -> UrlMap {      }  } -fn settings() -> Settings { +fn settings() -> Settings<impl Connectable> {      Settings {          installed_apps: &[              &polls::APP, diff --git a/examples/tutorial02/polls/migrations/mod.rs b/examples/tutorial02/polls/migrations/mod.rs new file mode 100644 index 0000000..64efe8d --- /dev/null +++ b/examples/tutorial02/polls/migrations/mod.rs @@ -0,0 +1,3 @@ +use tosin::db::migration::{Migration, gather}; + +gather!(); diff --git a/examples/tutorial02/polls/mod.rs b/examples/tutorial02/polls/mod.rs index f4fde54..4b5de71 100644 --- a/examples/tutorial02/polls/mod.rs +++ b/examples/tutorial02/polls/mod.rs @@ -1,5 +1,6 @@  use tosin::apps::AppConfig; +mod migrations;  pub mod models;  pub mod urls;  pub mod views; @@ -7,5 +8,5 @@ pub mod views;  pub use urls::urls;  pub const APP: AppConfig = AppConfig { - +    migrations: migrations::migrations,  }; diff --git a/src/bin/tosin-admin.rs b/src/bin/tosin-admin.rs index 6408337..e519d50 100644 --- a/src/bin/tosin-admin.rs +++ b/src/bin/tosin-admin.rs @@ -10,6 +10,7 @@ const TOSIN_DEPENDENCY: &str = concat!(r#"tosin = { path = ""#, env!("CARGO_MANI  const PROJECT_MAIN: &str = r#"  use tosin::Settings;  use tosin::contrib::admin; +use tosin::db::backend::Connectable;  use tosin::urls::{UrlMap, url_map};  fn urls() -> UrlMap { @@ -18,7 +19,7 @@ fn urls() -> UrlMap {      }  } -fn settings() -> Settings { +fn settings() -> Settings<impl Connectable> {      Settings {          ..Settings::default()      } diff --git a/src/cli/migrate.rs b/src/cli/migrate.rs new file mode 100644 index 0000000..4b5123a --- /dev/null +++ b/src/cli/migrate.rs @@ -0,0 +1,19 @@ +use structopt::StructOpt; + +use crate::{Settings, UrlMap, db::backend::{Connectable, Connection}}; + +#[derive(StructOpt)] +/// Perform database migrations +pub struct Migrate { +} + +impl Migrate { +    pub fn execute(self, _urls: UrlMap, settings: Settings<impl Connectable>) { +        let database = settings.database; +        let connection = database.connect().unwrap(); + +        let migration_table_vibe_check = connection.transaction::<(), diesel::result::Error, _>(|| { +            todo!() +        }); +    } +} diff --git a/src/cli/mod.rs b/src/cli/mod.rs index c656c1c..a11fd48 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,23 +1,26 @@  use structopt::StructOpt; -use crate::{Settings, UrlMap}; +use crate::{Settings, UrlMap, db::backend::Connectable}; +mod migrate;  mod run_server;  #[derive(StructOpt)]  enum Command { +    Migrate(migrate::Migrate),      RunServer(run_server::RunServer),  }  impl Command { -    fn execute(self, urls: UrlMap, settings: Settings) { +    fn execute(self, urls: UrlMap, settings: Settings<impl Connectable>) {          match self { +            Command::Migrate(command) => command.execute(urls, settings),              Command::RunServer(command) => command.execute(urls, settings),          }      }  } -pub fn main(urls: UrlMap, settings: Settings) { +pub fn main(urls: UrlMap, settings: Settings<impl Connectable>) {      let command = Command::from_args();      command.execute(urls, settings);  } diff --git a/src/cli/run_server.rs b/src/cli/run_server.rs index 242c824..66e6fe1 100644 --- a/src/cli/run_server.rs +++ b/src/cli/run_server.rs @@ -1,6 +1,6 @@  use structopt::StructOpt; -use crate::{Settings, UrlMap}; +use crate::{Settings, UrlMap, db::backend::Connectable};  #[derive(StructOpt)]  /// Run an HTTP server @@ -11,7 +11,7 @@ pub struct RunServer {  }  impl RunServer { -    pub fn execute(self, urls: UrlMap, _settings: Settings) { +    pub fn execute(self, urls: UrlMap, _settings: Settings<impl Connectable>) {          println!("Starting server at http://127.0.0.1:{}/", self.port);          let server_task = warp::serve(urls).run(([127, 0, 0, 1], self.port)); diff --git a/src/db/backend.rs b/src/db/backend.rs index 5ae4de2..b75d5ca 100644 --- a/src/db/backend.rs +++ b/src/db/backend.rs @@ -1,5 +1,18 @@ -pub enum DbBackend { -    Sqlite { -        db_file: &'static str, +pub use diesel::connection::Connection; + +pub trait Connectable { +    type Connection: Connection; +    fn connect(&self) -> diesel::ConnectionResult<Self::Connection>; +} + +pub struct Sqlite { +    pub db_file: &'static str, +} + +impl Connectable for Sqlite { +    type Connection = diesel::sqlite::SqliteConnection; + +    fn connect(&self) -> diesel::ConnectionResult<Self::Connection> { +        Self::Connection::establish(self.db_file)      }  } diff --git a/src/settings.rs b/src/settings.rs index 37a3395..4b140a6 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,15 +1,15 @@ -use crate::db::backend::DbBackend; +use crate::db::backend::{self, Connectable}; -pub struct Settings { +pub struct Settings<C: Connectable> {      pub installed_apps: &'static [&'static crate::apps::AppConfig], -    pub database: DbBackend, +    pub database: C,  } -impl Default for Settings { +impl Default for Settings<backend::Sqlite> {      fn default() -> Self {          Self {              installed_apps: &[], -            database: DbBackend::Sqlite { +            database: backend::Sqlite {                  db_file: "db.sqlite3",              },          } diff --git a/tests/tutorial/mod.rs b/tests/tutorial/mod.rs index 71cba3d..a9eb76f 100644 --- a/tests/tutorial/mod.rs +++ b/tests/tutorial/mod.rs @@ -44,7 +44,7 @@ fn get(url: &str) -> (hyper::StatusCode, String) {          .block_on(get)  } -pub fn step1(dest: &str) { +pub fn step1() {      // tosin-admin start-project {dest}      set_current_dir(PROJECT_DIR).unwrap();      set_current_dir("target").unwrap(); @@ -52,16 +52,16 @@ pub fn step1(dest: &str) {          fs::create_dir("tests").unwrap();      }      set_current_dir("tests").unwrap(); -    fs::write("Cargo.toml", "[workspace]\nmembers = ['tutorial1']").unwrap(); -    if fs::metadata(dest).is_ok() { -        fs::remove_dir_all(dest).unwrap(); +    fs::write("Cargo.toml", "[workspace]\nmembers = ['tutorial']").unwrap(); +    if fs::metadata("tutorial").is_ok() { +        fs::remove_dir_all("tutorial").unwrap();      }      Command::new(TOSIN_ADMIN) -        .args(&["start-project", dest]) +        .args(&["start-project", "tutorial"])          .status()          .unwrap()          .check(); -    set_current_dir(dest).unwrap(); +    set_current_dir("tutorial").unwrap();      assert!(fs::metadata("Cargo.toml").is_ok());      assert!(fs::read_to_string("Cargo.toml").unwrap().contains("tosin = "));      assert!(fs::metadata("src/main.rs").is_ok()); @@ -119,6 +119,7 @@ pub fn urls() -> UrlMap {      fs::write("src/main.rs", r#"  use tosin::Settings;  use tosin::contrib::admin; +use tosin::db::backend::Connectable;  use tosin::urls::{UrlMap, url_map};  mod polls; @@ -130,7 +131,7 @@ fn urls() -> UrlMap {      }  } -fn settings() -> Settings { +fn settings() -> Settings<impl Connectable> {      Settings {          ..Settings::default()      } @@ -169,7 +170,40 @@ tosin::main!(urls(), settings());      }  } -pub fn step2(dest: &str) { -    step1(dest); -    todo!(); +pub fn step2() { +    step1(); +    // update main.rs +    fs::write("src/main.rs", r#" +use tosin::Settings; +use tosin::contrib::admin; +use tosin::db::backend::Connectable; +use tosin::urls::{UrlMap, url_map}; + +mod polls; + +fn urls() -> UrlMap { +    url_map! { +        "polls" / ..polls::urls(), +        "admin" / ..admin::site::urls(), +    } +} + +fn settings() -> Settings<impl Connectable> { +    Settings { +        installed_apps: &[ +            &admin::APP, +        ], +        ..Settings::default() +    } +} + +tosin::main!(urls(), settings()); +    "#).unwrap(); + +    // cargo run migrate +    Command::new(CARGO) +        .args(&["run", "migrate"]) +        .status() +        .unwrap() +        .check();  } diff --git a/tests/tutorial_steps.rs b/tests/tutorial_steps.rs index 5af6eb5..63c05e8 100644 --- a/tests/tutorial_steps.rs +++ b/tests/tutorial_steps.rs @@ -3,11 +3,6 @@ mod tutorial;  use tutorial::*;  #[test] -fn tutorial1() { -    step1("tutorial1"); -} - -#[test]  fn tutorial2() { -    step2("tutorial2"); +    step2();  } |