aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn / boringcactus <melody@boringcactus.com>2021-06-18 10:12:16 -0600
committerMelody Horn / boringcactus <melody@boringcactus.com>2021-06-18 10:12:16 -0600
commit709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7 (patch)
treecc4aa6854147c0dc74bbd3bea9b8b9cfc083b62f
parent3b880c0ae7963d783fb87a3389f98070e448495a (diff)
downloadtosin-709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7.tar.gz
tosin-709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7.zip
make model metadata available in AppConfig
-rw-r--r--examples/tutorial01/polls/mod.rs2
-rw-r--r--examples/tutorial01/polls/models.rs5
-rw-r--r--examples/tutorial02/polls/mod.rs1
-rw-r--r--examples/tutorial02/polls/models.rs4
-rw-r--r--src/apps.rs2
-rw-r--r--src/bin/tosin-admin.rs7
-rw-r--r--src/contrib/admin/mod.rs2
-rw-r--r--src/contrib/admin/models.rs6
-rw-r--r--src/db/models/meta.rs3
-rw-r--r--src/db/models/mod.rs5
-rw-r--r--tests/tutorial/mod.rs4
-rw-r--r--tosin-macros/src/lib.rs41
12 files changed, 74 insertions, 8 deletions
diff --git a/examples/tutorial01/polls/mod.rs b/examples/tutorial01/polls/mod.rs
index 0b039d9..d15a1ca 100644
--- a/examples/tutorial01/polls/mod.rs
+++ b/examples/tutorial01/polls/mod.rs
@@ -7,7 +7,9 @@ pub mod views;
pub use urls::urls;
+#[allow(dead_code)]
pub const APP: AppConfig = AppConfig {
name: module_path!(),
+ models: models::ALL,
migrations: migrations::migrations,
};
diff --git a/examples/tutorial01/polls/models.rs b/examples/tutorial01/polls/models.rs
index 82aa7fd..bc1cd9b 100644
--- a/examples/tutorial01/polls/models.rs
+++ b/examples/tutorial01/polls/models.rs
@@ -1,3 +1,6 @@
-use tosin::db::models::{Model, Id};
+#[allow(unused_imports)]
+use tosin::db::models::{Model, Id, gather};
// TODO define models
+
+gather!();
diff --git a/examples/tutorial02/polls/mod.rs b/examples/tutorial02/polls/mod.rs
index 0b039d9..1968d5a 100644
--- a/examples/tutorial02/polls/mod.rs
+++ b/examples/tutorial02/polls/mod.rs
@@ -9,5 +9,6 @@ pub use urls::urls;
pub const APP: AppConfig = AppConfig {
name: module_path!(),
+ models: models::ALL,
migrations: migrations::migrations,
};
diff --git a/examples/tutorial02/polls/models.rs b/examples/tutorial02/polls/models.rs
index 5ed52c5..fb8be8f 100644
--- a/examples/tutorial02/polls/models.rs
+++ b/examples/tutorial02/polls/models.rs
@@ -1,4 +1,4 @@
-use tosin::db::models::{Model, Id};
+use tosin::db::models::{Model, Id, gather};
#[derive(Model)]
pub struct Question {
@@ -19,3 +19,5 @@ pub struct Choice {
#[model(default = 0)]
votes: usize,
}
+
+gather!();
diff --git a/src/apps.rs b/src/apps.rs
index f72a883..8c16136 100644
--- a/src/apps.rs
+++ b/src/apps.rs
@@ -1,6 +1,8 @@
use crate::db::migration::Migration;
+use crate::db::models::ModelMeta;
pub struct AppConfig {
pub name: &'static str,
+ pub models: &'static [ModelMeta],
pub migrations: &'static [Migration],
}
diff --git a/src/bin/tosin-admin.rs b/src/bin/tosin-admin.rs
index 0a359d3..a0ea850 100644
--- a/src/bin/tosin-admin.rs
+++ b/src/bin/tosin-admin.rs
@@ -38,8 +38,10 @@ pub mod views;
pub use urls::urls;
+#[allow(dead_code)]
pub const APP: AppConfig = AppConfig {
name: module_path!(),
+ models: models::ALL,
migrations: migrations::migrations,
};
"#;
@@ -49,9 +51,12 @@ use tosin::db::migration::{Migration, gather};
gather!();
"#;
const APP_MODELS: &str = r#"
-use tosin::db::models::{Model, Id};
+#[allow(unused_imports)]
+use tosin::db::models::{Model, Id, gather};
// TODO define models
+
+gather!();
"#;
const APP_URLS: &str = r#"
use tosin::urls::{UrlMap, url_map};
diff --git a/src/contrib/admin/mod.rs b/src/contrib/admin/mod.rs
index f92e709..8572f8d 100644
--- a/src/contrib/admin/mod.rs
+++ b/src/contrib/admin/mod.rs
@@ -1,9 +1,11 @@
use crate::apps::AppConfig;
mod migrations;
+mod models;
pub mod site;
pub const APP: AppConfig = AppConfig {
name: module_path!(),
+ models: models::ALL,
migrations: migrations::migrations,
};
diff --git a/src/contrib/admin/models.rs b/src/contrib/admin/models.rs
new file mode 100644
index 0000000..7fde44a
--- /dev/null
+++ b/src/contrib/admin/models.rs
@@ -0,0 +1,6 @@
+#[allow(unused_imports)]
+use crate::db::models::{Model, Id, ModelMeta};
+
+pub const ALL: &[ModelMeta] = &[
+
+];
diff --git a/src/db/models/meta.rs b/src/db/models/meta.rs
new file mode 100644
index 0000000..50729a8
--- /dev/null
+++ b/src/db/models/meta.rs
@@ -0,0 +1,3 @@
+pub struct ModelMeta {
+ pub name: &'static str,
+}
diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs
index 492df92..feadb43 100644
--- a/src/db/models/mod.rs
+++ b/src/db/models/mod.rs
@@ -1,4 +1,7 @@
-pub use tosin_macros::Model;
+pub use tosin_macros::{Model, gather_models as gather};
+
+mod meta;
+pub use meta::*;
pub type Id = usize;
diff --git a/tests/tutorial/mod.rs b/tests/tutorial/mod.rs
index 0bd626e..fb05066 100644
--- a/tests/tutorial/mod.rs
+++ b/tests/tutorial/mod.rs
@@ -223,7 +223,7 @@ tosin = { path = "/home/cactus/Documents/tosin" }
// update polls/models.rs
fs::write("src/polls/models.rs", r#"
-use tosin::db::models::{Model, Id};
+use tosin::db::models::{Model, Id, gather};
#[derive(Model)]
pub struct Question {
@@ -244,6 +244,8 @@ pub struct Choice {
#[model(default = 0)]
votes: usize,
}
+
+gather!();
"#).unwrap();
// update main.rs
diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs
index 7efbac6..408378f 100644
--- a/tosin-macros/src/lib.rs
+++ b/tosin-macros/src/lib.rs
@@ -2,6 +2,8 @@
extern crate proc_macro;
+use std::fs;
+
use proc_macro::TokenStream;
use quote::quote;
@@ -19,9 +21,9 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
impl #name {
- fn hello_macro() {
- println!("Hello, Macro! My name is {}!", stringify!(#name));
- }
+ pub const META: tosin::db::models::ModelMeta = tosin::db::models::ModelMeta {
+ name: stringify!(#name),
+ };
}
};
gen.into()
@@ -55,3 +57,36 @@ pub fn gather_migrations(_input: TokenStream) -> TokenStream {
gen.into()
}
+
+#[proc_macro]
+pub fn gather_models(_input: TokenStream) -> TokenStream {
+ let call_site = proc_macro::Span::call_site();
+ let call_site_file = call_site.source_file();
+ let call_site_path = call_site_file.path();
+ if !call_site_file.is_real() {
+ panic!("call site does not have a real path");
+ }
+
+ let call_site_ast = syn::parse_file(&fs::read_to_string(call_site_path).unwrap()).unwrap();
+ let models = call_site_ast.items.iter()
+ .filter_map(|item| if let syn::Item::Struct(item) = item { Some(item) } else { None })
+ .filter(|item| item.attrs.iter().any(|attr| {
+ let attr = if let Ok(syn::Meta::List(attr)) = attr.parse_meta() { attr } else { return false; };
+ if attr.path.get_ident().map_or(false, |hopefully_derive| hopefully_derive == "derive") {
+ let mut derived = attr.nested.iter()
+ .filter_map(|derived| if let syn::NestedMeta::Meta(derived) = derived { Some(derived) } else { None });
+ derived.any(|derived| derived.path().get_ident().map_or(false, |hopefully_model| hopefully_model == "Model"))
+ } else {
+ false
+ }
+ }))
+ .map(|item| &item.ident);
+
+ let gen = quote! {
+ pub const ALL: &[tosin::db::models::ModelMeta] = &[
+ #(#models::META),*
+ ];
+ };
+
+ gen.into()
+}