Skip to content

Commit

Permalink
Add the protected annotation in deriving ModelHooks
Browse files Browse the repository at this point in the history
  • Loading branch information
photino committed Feb 19, 2025
1 parent 4650f98 commit 5270f1f
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 19 deletions.
10 changes: 10 additions & 0 deletions crates/zino-core/src/extension/json_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ pub trait JsonObjectExt {
/// Extracts values from the populated data corresponding to the key and moves them to `self`.
fn extract_from_populated(&mut self, key: &str, fields: &[&str]);

/// Removes all the entries for the keys.
fn remove_all(&mut self, keys: &[&str]);

/// Renames all the keys to the specific case.
fn rename_keys(&mut self, case: Case);

Expand Down Expand Up @@ -775,6 +778,13 @@ impl JsonObjectExt for Map {
self.append(&mut object);
}

#[inline]
fn remove_all(&mut self, keys: &[&str]) {
for &key in keys {
self.remove(key);
}
}

#[inline]
fn rename_keys(&mut self, case: Case) {
for (key, value) in mem::take(self) {
Expand Down
6 changes: 6 additions & 0 deletions crates/zino-core/src/model/hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,12 @@ pub trait ModelHooks: Model {
Ok(())
}

/// A hook running after a query population for the model.
#[inline]
async fn after_populate(_model: &mut Map) -> Result<(), Error> {
Ok(())
}

/// A hook running after decoding the model as a `Map`.
#[inline]
async fn after_decode(_model: &mut Map) -> Result<(), Error> {
Expand Down
3 changes: 3 additions & 0 deletions crates/zino-derive/docs/model_accessor.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Derives the [`ModelAccessor`](zino_orm::ModelAccessor) trait.
- **`#[schema(primary_key)]`**: The `primary_key` annotation is used to
mark a column as the primary key.

- **`#[schema(protected)]`**: The `protected` annotation is used to indicate that
the column should not be included in a query population.

- **`#[schema(snapshot)]`**: The `snapshot` annotation is used to indicate that
the column should be included in a query population. Built-in snapshot fields:
`id` | `name` | `status` | `updated_at` | `version`.
Expand Down
31 changes: 31 additions & 0 deletions crates/zino-derive/src/model_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,37 @@ pub(super) fn parse_token_stream(input: DeriveInput) -> TokenStream {
});
}

// Parsing field attributes
let mut protected_fields = Vec::new();
for field in parser::parse_struct_fields(input.data) {
if let Some(ident) = field.ident {
let mut protected = false;
for attr in field.attrs.iter() {
let arguments = parser::parse_schema_attr(attr);
for (key, _value) in arguments.into_iter() {
if key == "protected" {
protected = true;
}
}
}
if protected {
let name = ident.to_string().trim_start_matches("r#").to_owned();
protected_fields.push(name);
}
}
}
if !protected_fields.is_empty() {
model_hooks.push(quote! {
#[inline]
async fn after_populate(model: &mut zino_core::Map) -> Result<(), zino_core::error::Error> {
use zino_core::extension::JsonObjectExt;

model.remove_all(&[#(#protected_fields),*]);
Ok(())
}
});
}

quote! {
impl zino_core::model::ModelHooks for #name {
type Data = ();
Expand Down
12 changes: 6 additions & 6 deletions crates/zino-dioxus/src/form/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ pub fn FileUpload(props: FileUploadProps) -> Element {
class: "file-cta",
span {
class: "file-icon",
if props.icon.is_some() {
{ props.icon }
if let Some(icon) = props.icon {
{ icon }
} else {
SvgIcon {
shape: FaUpload,
Expand All @@ -69,10 +69,10 @@ pub fn FileUpload(props: FileUploadProps) -> Element {
{ props.label }
}
}
if props.children.is_some() {
if let Some(children) = props.children {
span {
class: "file-name",
{ props.children }
{ children }
}
} else if !file_names().is_empty() {
span {
Expand Down Expand Up @@ -110,14 +110,14 @@ pub struct FileUploadProps {
#[props(into)]
pub label: SharedString,
/// An optional upload icon.
pub icon: Option<VNode>,
pub icon: Option<Element>,
/// An event handler to be called when the files are selected.
pub on_change: Option<EventHandler<Vec<NamedFile>>>,
/// Spreading the props of the `input` element.
#[props(extends = input)]
attributes: Vec<Attribute>,
/// The children to render within the component.
children: Option<VNode>,
children: Option<Element>,
}

/// A list of files and folders in a hierarchical tree structure.
Expand Down
12 changes: 6 additions & 6 deletions crates/zino-dioxus/src/navigation/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ pub fn Pagination(props: PaginationProps) -> Element {
handler.call(current_page - 1);
}
},
if props.prev.is_some() {
{ props.prev }
if let Some(prev) = props.prev {
{ prev }
} else {
SvgIcon {
shape: FaArrowLeft,
Expand Down Expand Up @@ -178,8 +178,8 @@ pub fn Pagination(props: PaginationProps) -> Element {
handler.call(current_page + 1);
}
},
if props.next.is_some() {
{ props.next }
if let Some(next) = props.next {
{ next }
} else {
span {
class: "mr-1",
Expand Down Expand Up @@ -215,9 +215,9 @@ pub struct PaginationProps {
#[props(into, default = "Next")]
pub next_text: SharedString,
/// The element for the previous button.
pub prev: Option<VNode>,
pub prev: Option<Element>,
/// The element for the next button.
pub next: Option<VNode>,
pub next: Option<Element>,
/// An event handler to be called when the page number is changed.
pub on_change: Option<EventHandler<usize>>,
}
6 changes: 3 additions & 3 deletions crates/zino-dioxus/src/typography/card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ pub fn Card(props: CardProps) -> Element {
{ props.content }
}
}
if props.footer.is_some() {
if let Some(footer) = props.footer {
footer {
class: "card-footer",
{ props.footer }
{ footer }
}
}
}
Expand All @@ -41,5 +41,5 @@ pub struct CardProps {
/// The modal content to render within the component.
pub content: Element,
/// The modal footer to render within the component.
pub footer: Option<VNode>,
pub footer: Option<Element>,
}
26 changes: 22 additions & 4 deletions crates/zino-orm/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,13 @@ pub(super) trait QueryExt<DB> {
format!(r#"{field} = {value}"#)
}
}
JsonValue::Number(n) => {
if cfg!(feature = "orm-postgres") {
format!(r#"{field} {operator} '{n}'"#)
} else {
format!(r#"{field} {operator} {n}"#)
}
}
JsonValue::String(s) => {
if s == "null" {
format!(r#"{field} IS NULL"#)
Expand All @@ -1306,14 +1313,25 @@ pub(super) trait QueryExt<DB> {
} else {
format!(r#"{field} = {s}"#)
}
} else if let Ok(value) = s.parse::<serde_json::Number>() {
format!(r#"{field} {operator} {value}"#)
} else if let Ok(n) = s.parse::<serde_json::Number>() {
if cfg!(feature = "orm-postgres") {
format!(r#"{field} {operator} '{n}'"#)
} else {
format!(r#"{field} {operator} {n}"#)
}
} else {
let value = Self::escape_string(value);
let value = if cfg!(feature = "orm-postgres") {
Self::escape_string(value)
} else {
Self::escape_string(s)
};
format!(r#"{field} {operator} {value}"#)
}
}
_ => format!(r#"{field} {operator} {value}"#),
_ => {
let value = Self::escape_string(value);
format!(r#"{field} {operator} {value}"#)
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/zino-orm/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
for row in rows {
let mut map = Map::decode_row(&row)?;
let primary_key = map.get(primary_key_name).cloned();
Self::after_populate(&mut map).await?;
translate_enabled.then(|| Self::translate_model(&mut map));
Self::after_decode(&mut map).await?;
if let Some(key) = primary_key {
Expand Down Expand Up @@ -1279,6 +1280,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
for row in rows {
let mut map = Map::decode_row(&row)?;
let primary_key = map.get(primary_key_name).cloned();
Self::after_populate(&mut map).await?;
translate_enabled.then(|| Self::translate_model(&mut map));
Self::after_decode(&mut map).await?;
if let Some(key) = primary_key {
Expand Down

0 comments on commit 5270f1f

Please sign in to comment.