ormlite_attr/metadata/
model.rs1use crate::metadata::column::ColumnMeta;
2use crate::metadata::table::TableMeta;
3use crate::Ident;
4use crate::TableAttr;
5use syn::DeriveInput;
6
7#[derive(Debug, Clone)]
9pub struct ModelMeta {
10 pub table: TableMeta,
11 pub insert_struct: Option<Ident>,
12 pub extra_derives: Option<Vec<Ident>>,
13 pub pkey: ColumnMeta,
14}
15
16impl ModelMeta {
17 pub fn builder_struct(&self) -> Ident {
18 Ident::from(format!("{}Builder", self.ident.as_ref()))
19 }
20
21 pub fn database_columns_except_pkey(&self) -> impl Iterator<Item = &ColumnMeta> + '_ {
22 self.columns
23 .iter()
24 .filter(|&c| !c.skip)
25 .filter(|&c| self.pkey.name != c.name)
26 }
27
28 pub fn from_derive(ast: &DeriveInput) -> Self {
29 let attrs = TableAttr::from_attrs(&ast.attrs);
30 let table = TableMeta::new(ast, &attrs);
31 let pkey = table.pkey.as_deref().expect(&format!(
32 "No column marked with #[ormlite(primary_key)], and no column named id, uuid, {0}_id, or {0}_uuid",
33 table.name,
34 ));
35 let mut insert_struct = None;
36 let mut extra_derives: Option<Vec<syn::Ident>> = None;
37 for attr in attrs {
38 if let Some(v) = attr.insert {
39 insert_struct = Some(v.value());
40 }
41 if let Some(v) = attr.insertable {
42 insert_struct = Some(v.to_string());
43 }
44 if let Some(v) = attr.extra_derives {
45 if !v.is_empty() {
46 extra_derives = Some(v);
47 }
48 }
49 }
50 let pkey = table.columns.iter().find(|&c| c.name == pkey).unwrap().clone();
51 let insert_struct = insert_struct.map(|v| Ident::from(v));
52 let extra_derives = extra_derives.take().map(|vec| vec.into_iter().map(|v| v.to_string()).map(Ident::from).collect());
53
54 Self {
55 table,
56 insert_struct,
57 extra_derives,
58 pkey,
59 }
60 }
61
62 #[doc(hidden)]
63 pub fn mock(name: &str, columns: Vec<ColumnMeta>) -> Self {
64 let inner = TableMeta::mock(name, columns);
65 Self {
66 pkey: inner.columns.iter().find(|c| c.name == "id").unwrap().clone(),
67 table: inner,
68 extra_derives: None,
69 insert_struct: None,
70 }
71 }
72}
73
74impl std::ops::Deref for ModelMeta {
75 type Target = TableMeta;
76
77 fn deref(&self) -> &Self::Target {
78 &self.table
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use syn::ItemStruct;
86
87 #[test]
88 fn test_decode_metadata() {
89 let ast = syn::parse_str::<ItemStruct>(
90 r#"struct User {
91 #[ormlite(column = "Id")]
92 id: i32,
93 }"#,
94 )
95 .unwrap();
96 let input = DeriveInput::from(ast);
97 let meta = ModelMeta::from_derive(&input);
98 assert_eq!(meta.pkey.name, "Id");
99 }
100}