From 2a2ce85381df90485df6cf7de4537133b08ae762 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Sun, 23 May 2021 23:28:11 +0300 Subject: [PATCH] refac: add utils for migration list --- migra/src/migration.rs | 156 +++++++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 36 deletions(-) diff --git a/migra/src/migration.rs b/migra/src/migration.rs index 6f66cb9..a7a82a7 100644 --- a/migra/src/migration.rs +++ b/migra/src/migration.rs @@ -1,8 +1,8 @@ +use std::iter::FromIterator; + #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct Migration { name: String, - upgrade_sql_content: Option, - downgrade_sql_content: Option, } impl Migration { @@ -10,25 +10,6 @@ impl Migration { pub fn new(name: &str) -> Self { Migration { name: name.to_owned(), - ..Migration::default() - } - } - - #[must_use] - pub fn with_upgrade(name: &str, up_content: &str) -> Self { - Migration { - name: name.to_owned(), - upgrade_sql_content: Some(up_content.to_owned()), - ..Migration::default() - } - } - - #[must_use] - pub fn with_upgrade_and_downgrade(name: &str, up_content: &str, down_content: &str) -> Self { - Migration { - name: name.to_owned(), - upgrade_sql_content: Some(up_content.to_owned()), - downgrade_sql_content: Some(down_content.to_owned()), } } @@ -36,19 +17,9 @@ impl Migration { pub fn name(&self) -> &String { &self.name } - - #[must_use] - pub fn upgrade_sql_content(&self) -> Option<&String> { - self.upgrade_sql_content.as_ref() - } - - #[must_use] - pub fn downgrade_sql_content(&self) -> Option<&String> { - self.downgrade_sql_content.as_ref() - } } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct List { inner: Vec, } @@ -61,27 +32,140 @@ impl> From> for List { } } +impl std::ops::Deref for List { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + impl List { #[must_use] pub fn new() -> Self { List { inner: Vec::new() } } - pub fn push>(&mut self, name: &T) { - self.inner.push(Migration::new(name.as_ref())) + pub fn push(&mut self, migration: Migration) { + self.inner.push(migration) + } + + pub fn push_name(&mut self, name: &str) { + self.inner.push(Migration::new(name)) } #[must_use] - pub fn contains(&self, name: &str) -> bool { + pub fn contains(&self, other_migration: &Migration) -> bool { + self.inner + .iter() + .any(|migration| migration == other_migration) + } + + #[must_use] + pub fn contains_name(&self, name: &str) -> bool { self.inner.iter().any(|migration| migration.name() == name) } #[must_use] pub fn maybe_next<'a>(&self, name: &'a str) -> Option<&'a str> { - if self.contains(name) { + if self.contains_name(name) { None } else { Some(name) } } + + #[must_use] + pub fn exclude(&self, list: &List) -> List { + self.iter() + .filter(|migration| !list.contains(migration)) + .collect() + } +} + +impl FromIterator for List { + fn from_iter>(iter: I) -> Self { + let mut list = List::new(); + + for item in iter { + list.push(item); + } + + list + } +} + +impl<'a> FromIterator<&'a Migration> for List { + fn from_iter>(iter: I) -> Self { + let mut list = List::new(); + + for item in iter { + list.push(item.clone()); + } + + list + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const FIRST_MIGRATION: &str = "initial_migration"; + const SECOND_MIGRATION: &str = "new_migration"; + + #[test] + fn push_migration_to_list() { + let mut list = List::new(); + + list.push(Migration::new(FIRST_MIGRATION)); + assert_eq!(list, List::from(vec![FIRST_MIGRATION])); + + list.push(Migration::new(&String::from(SECOND_MIGRATION))); + assert_eq!(list, List::from(vec![FIRST_MIGRATION, SECOND_MIGRATION])) + } + + #[test] + fn push_name_to_list() { + let mut list = List::new(); + + list.push_name(FIRST_MIGRATION); + assert_eq!(list, List::from(vec![FIRST_MIGRATION])); + + list.push_name(&String::from(SECOND_MIGRATION)); + assert_eq!(list, List::from(vec![FIRST_MIGRATION, SECOND_MIGRATION])) + } + + #[test] + fn contains_migration() { + let list = List::from(vec![FIRST_MIGRATION]); + + assert_eq!(list.contains(&Migration::new(FIRST_MIGRATION)), true); + assert_eq!(list.contains(&Migration::new(SECOND_MIGRATION)), false); + } + + #[test] + fn contains_migration_name() { + let list = List::from(vec![FIRST_MIGRATION]); + + assert_eq!(list.contains_name(FIRST_MIGRATION), true); + assert_eq!(list.contains_name(SECOND_MIGRATION), false); + } + + #[test] + fn maybe_next_migration_name() { + let list = List::from(vec![FIRST_MIGRATION]); + + assert_eq!(list.maybe_next(FIRST_MIGRATION), None); + assert_eq!(list.maybe_next(SECOND_MIGRATION), Some(SECOND_MIGRATION)); + } + + #[test] + fn create_excluded_migration_list() { + let all_migrations = List::from(vec![FIRST_MIGRATION, SECOND_MIGRATION]); + let applied_migrations = List::from(vec![FIRST_MIGRATION]); + let excluded = all_migrations.exclude(&applied_migrations); + + assert_eq!(excluded, List::from(vec![SECOND_MIGRATION])) + } }