rjango 0.1.1

A full-stack Rust backend framework inspired by Django
Documentation
/// Generate an admin configuration type from a compact declaration.
#[macro_export]
macro_rules! admin {
    (
        $admin_name:ident for $model_name:ident {
            $( $option:ident : [ $($values:tt)* ] ),* $(,)?
        }
    ) => {
        #[doc = concat!("Admin configuration for ", stringify!($model_name), ".")]
        pub struct $admin_name;

        impl $admin_name {
            $(
                pub fn $option() -> Vec<&'static str> {
                    $crate::__rjango_admin_vec!($($values)*)
                }
            )*
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __rjango_admin_vec {
    () => {
        ::std::vec::Vec::<&'static str>::new()
    };
    (- $value:ident) => {
        ::std::vec![concat!("-", stringify!($value))]
    };
    (- $value:ident, $($rest:tt)*) => {{
        let mut values = ::std::vec![concat!("-", stringify!($value))];
        values.extend($crate::__rjango_admin_vec!($($rest)*));
        values
    }};
    ($value:ident) => {
        ::std::vec![stringify!($value)]
    };
    ($value:ident, $($rest:tt)*) => {{
        let mut values = ::std::vec![stringify!($value)];
        values.extend($crate::__rjango_admin_vec!($($rest)*));
        values
    }};
    ($value:literal) => {
        ::std::vec![$value]
    };
    ($value:literal, $($rest:tt)*) => {{
        let mut values = ::std::vec![$value];
        values.extend($crate::__rjango_admin_vec!($($rest)*));
        values
    }};
}

#[cfg(test)]
mod tests {
    mod configured_admin {
        crate::admin! {
            BlogPostAdmin for BlogPost {
                list_display: [title, slug, created_at],
                list_filter: [created_at],
                search_fields: [title, body],
                ordering: [-created_at],
            }
        }

        #[test]
        fn admin_macro_creates_struct() {
            let _admin = BlogPostAdmin;
        }

        #[test]
        fn admin_macro_list_display() {
            assert_eq!(
                BlogPostAdmin::list_display(),
                vec!["title", "slug", "created_at"]
            );
        }

        #[test]
        fn admin_macro_list_filter() {
            assert_eq!(BlogPostAdmin::list_filter(), vec!["created_at"]);
        }

        #[test]
        fn admin_macro_search_fields() {
            assert_eq!(BlogPostAdmin::search_fields(), vec!["title", "body"]);
        }

        #[test]
        fn admin_macro_ordering() {
            assert_eq!(BlogPostAdmin::ordering(), vec!["-created_at"]);
        }
    }

    mod empty_admin {
        crate::admin! {
            EmptyAdmin for EmptyModel {
                list_display: [],
                list_filter: [],
                ordering: [],
            }
        }

        #[test]
        fn admin_macro_empty_options() {
            assert!(EmptyAdmin::list_display().is_empty());
            assert!(EmptyAdmin::list_filter().is_empty());
            assert!(EmptyAdmin::ordering().is_empty());
        }
    }

    mod trailing_comma_admin {
        crate::admin! {
            TrailingCommaAdmin for TrailingCommaModel {
                list_display: [title,],
                search_fields: [body,],
            }
        }

        #[test]
        fn admin_macro_trailing_comma() {
            assert_eq!(TrailingCommaAdmin::list_display(), vec!["title"]);
            assert_eq!(TrailingCommaAdmin::search_fields(), vec!["body"]);
        }
    }
}