Skip to content

Commit 5270f1f

Browse files
committed
Add the protected annotation in deriving ModelHooks
1 parent 4650f98 commit 5270f1f

File tree

9 files changed

+89
-19
lines changed

9 files changed

+89
-19
lines changed

crates/zino-core/src/extension/json_object.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ pub trait JsonObjectExt {
248248
/// Extracts values from the populated data corresponding to the key and moves them to `self`.
249249
fn extract_from_populated(&mut self, key: &str, fields: &[&str]);
250250

251+
/// Removes all the entries for the keys.
252+
fn remove_all(&mut self, keys: &[&str]);
253+
251254
/// Renames all the keys to the specific case.
252255
fn rename_keys(&mut self, case: Case);
253256

@@ -775,6 +778,13 @@ impl JsonObjectExt for Map {
775778
self.append(&mut object);
776779
}
777780

781+
#[inline]
782+
fn remove_all(&mut self, keys: &[&str]) {
783+
for &key in keys {
784+
self.remove(key);
785+
}
786+
}
787+
778788
#[inline]
779789
fn rename_keys(&mut self, case: Case) {
780790
for (key, value) in mem::take(self) {

crates/zino-core/src/model/hook.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ pub trait ModelHooks: Model {
312312
Ok(())
313313
}
314314

315+
/// A hook running after a query population for the model.
316+
#[inline]
317+
async fn after_populate(_model: &mut Map) -> Result<(), Error> {
318+
Ok(())
319+
}
320+
315321
/// A hook running after decoding the model as a `Map`.
316322
#[inline]
317323
async fn after_decode(_model: &mut Map) -> Result<(), Error> {

crates/zino-derive/docs/model_accessor.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Derives the [`ModelAccessor`](zino_orm::ModelAccessor) trait.
1616
- **`#[schema(primary_key)]`**: The `primary_key` annotation is used to
1717
mark a column as the primary key.
1818

19+
- **`#[schema(protected)]`**: The `protected` annotation is used to indicate that
20+
the column should not be included in a query population.
21+
1922
- **`#[schema(snapshot)]`**: The `snapshot` annotation is used to indicate that
2023
the column should be included in a query population. Built-in snapshot fields:
2124
`id` | `name` | `status` | `updated_at` | `version`.

crates/zino-derive/src/model_hooks.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,37 @@ pub(super) fn parse_token_stream(input: DeriveInput) -> TokenStream {
4444
});
4545
}
4646

47+
// Parsing field attributes
48+
let mut protected_fields = Vec::new();
49+
for field in parser::parse_struct_fields(input.data) {
50+
if let Some(ident) = field.ident {
51+
let mut protected = false;
52+
for attr in field.attrs.iter() {
53+
let arguments = parser::parse_schema_attr(attr);
54+
for (key, _value) in arguments.into_iter() {
55+
if key == "protected" {
56+
protected = true;
57+
}
58+
}
59+
}
60+
if protected {
61+
let name = ident.to_string().trim_start_matches("r#").to_owned();
62+
protected_fields.push(name);
63+
}
64+
}
65+
}
66+
if !protected_fields.is_empty() {
67+
model_hooks.push(quote! {
68+
#[inline]
69+
async fn after_populate(model: &mut zino_core::Map) -> Result<(), zino_core::error::Error> {
70+
use zino_core::extension::JsonObjectExt;
71+
72+
model.remove_all(&[#(#protected_fields),*]);
73+
Ok(())
74+
}
75+
});
76+
}
77+
4778
quote! {
4879
impl zino_core::model::ModelHooks for #name {
4980
type Data = ();

crates/zino-dioxus/src/form/file.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ pub fn FileUpload(props: FileUploadProps) -> Element {
5555
class: "file-cta",
5656
span {
5757
class: "file-icon",
58-
if props.icon.is_some() {
59-
{ props.icon }
58+
if let Some(icon) = props.icon {
59+
{ icon }
6060
} else {
6161
SvgIcon {
6262
shape: FaUpload,
@@ -69,10 +69,10 @@ pub fn FileUpload(props: FileUploadProps) -> Element {
6969
{ props.label }
7070
}
7171
}
72-
if props.children.is_some() {
72+
if let Some(children) = props.children {
7373
span {
7474
class: "file-name",
75-
{ props.children }
75+
{ children }
7676
}
7777
} else if !file_names().is_empty() {
7878
span {
@@ -110,14 +110,14 @@ pub struct FileUploadProps {
110110
#[props(into)]
111111
pub label: SharedString,
112112
/// An optional upload icon.
113-
pub icon: Option<VNode>,
113+
pub icon: Option<Element>,
114114
/// An event handler to be called when the files are selected.
115115
pub on_change: Option<EventHandler<Vec<NamedFile>>>,
116116
/// Spreading the props of the `input` element.
117117
#[props(extends = input)]
118118
attributes: Vec<Attribute>,
119119
/// The children to render within the component.
120-
children: Option<VNode>,
120+
children: Option<Element>,
121121
}
122122

123123
/// A list of files and folders in a hierarchical tree structure.

crates/zino-dioxus/src/navigation/pagination.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ pub fn Pagination(props: PaginationProps) -> Element {
2323
handler.call(current_page - 1);
2424
}
2525
},
26-
if props.prev.is_some() {
27-
{ props.prev }
26+
if let Some(prev) = props.prev {
27+
{ prev }
2828
} else {
2929
SvgIcon {
3030
shape: FaArrowLeft,
@@ -178,8 +178,8 @@ pub fn Pagination(props: PaginationProps) -> Element {
178178
handler.call(current_page + 1);
179179
}
180180
},
181-
if props.next.is_some() {
182-
{ props.next }
181+
if let Some(next) = props.next {
182+
{ next }
183183
} else {
184184
span {
185185
class: "mr-1",
@@ -215,9 +215,9 @@ pub struct PaginationProps {
215215
#[props(into, default = "Next")]
216216
pub next_text: SharedString,
217217
/// The element for the previous button.
218-
pub prev: Option<VNode>,
218+
pub prev: Option<Element>,
219219
/// The element for the next button.
220-
pub next: Option<VNode>,
220+
pub next: Option<Element>,
221221
/// An event handler to be called when the page number is changed.
222222
pub on_change: Option<EventHandler<usize>>,
223223
}

crates/zino-dioxus/src/typography/card.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ pub fn Card(props: CardProps) -> Element {
2020
{ props.content }
2121
}
2222
}
23-
if props.footer.is_some() {
23+
if let Some(footer) = props.footer {
2424
footer {
2525
class: "card-footer",
26-
{ props.footer }
26+
{ footer }
2727
}
2828
}
2929
}
@@ -41,5 +41,5 @@ pub struct CardProps {
4141
/// The modal content to render within the component.
4242
pub content: Element,
4343
/// The modal footer to render within the component.
44-
pub footer: Option<VNode>,
44+
pub footer: Option<Element>,
4545
}

crates/zino-orm/src/query.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,13 @@ pub(super) trait QueryExt<DB> {
12951295
format!(r#"{field} = {value}"#)
12961296
}
12971297
}
1298+
JsonValue::Number(n) => {
1299+
if cfg!(feature = "orm-postgres") {
1300+
format!(r#"{field} {operator} '{n}'"#)
1301+
} else {
1302+
format!(r#"{field} {operator} {n}"#)
1303+
}
1304+
}
12981305
JsonValue::String(s) => {
12991306
if s == "null" {
13001307
format!(r#"{field} IS NULL"#)
@@ -1306,14 +1313,25 @@ pub(super) trait QueryExt<DB> {
13061313
} else {
13071314
format!(r#"{field} = {s}"#)
13081315
}
1309-
} else if let Ok(value) = s.parse::<serde_json::Number>() {
1310-
format!(r#"{field} {operator} {value}"#)
1316+
} else if let Ok(n) = s.parse::<serde_json::Number>() {
1317+
if cfg!(feature = "orm-postgres") {
1318+
format!(r#"{field} {operator} '{n}'"#)
1319+
} else {
1320+
format!(r#"{field} {operator} {n}"#)
1321+
}
13111322
} else {
1312-
let value = Self::escape_string(value);
1323+
let value = if cfg!(feature = "orm-postgres") {
1324+
Self::escape_string(value)
1325+
} else {
1326+
Self::escape_string(s)
1327+
};
13131328
format!(r#"{field} {operator} {value}"#)
13141329
}
13151330
}
1316-
_ => format!(r#"{field} {operator} {value}"#),
1331+
_ => {
1332+
let value = Self::escape_string(value);
1333+
format!(r#"{field} {operator} {value}"#)
1334+
}
13171335
}
13181336
}
13191337

crates/zino-orm/src/schema.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
11871187
for row in rows {
11881188
let mut map = Map::decode_row(&row)?;
11891189
let primary_key = map.get(primary_key_name).cloned();
1190+
Self::after_populate(&mut map).await?;
11901191
translate_enabled.then(|| Self::translate_model(&mut map));
11911192
Self::after_decode(&mut map).await?;
11921193
if let Some(key) = primary_key {
@@ -1279,6 +1280,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
12791280
for row in rows {
12801281
let mut map = Map::decode_row(&row)?;
12811282
let primary_key = map.get(primary_key_name).cloned();
1283+
Self::after_populate(&mut map).await?;
12821284
translate_enabled.then(|| Self::translate_model(&mut map));
12831285
Self::after_decode(&mut map).await?;
12841286
if let Some(key) = primary_key {

0 commit comments

Comments
 (0)