...
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::model::{BaseModel, BaseModelData, IndexKey};
|
||||
|
||||
/// Represents a comment on a model
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Comment {
|
||||
/// Base model data
|
||||
pub base_data: BaseModelData,
|
||||
|
||||
/// The ID of the user who created the comment
|
||||
pub user_id: u32,
|
||||
|
||||
/// The ID of the model this comment is attached to
|
||||
pub model_id: u32,
|
||||
|
||||
/// The type of model this comment is attached to
|
||||
pub model_type: String,
|
||||
|
||||
/// The content of the comment
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Comment {
|
||||
/// Create a new comment
|
||||
pub fn new(id: u32, user_id: u32, model_id: u32, model_type: String, content: String) -> Self {
|
||||
Self {
|
||||
base_data: BaseModelData::new(id),
|
||||
user_id,
|
||||
model_id,
|
||||
model_type,
|
||||
content,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the comment content
|
||||
pub fn update_content(&mut self, content: String) {
|
||||
self.content = content;
|
||||
self.base_data.update_modified();
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseModel for Comment {
|
||||
fn db_prefix() -> &'static str {
|
||||
"comment"
|
||||
}
|
||||
|
||||
fn get_id(&self) -> u32 {
|
||||
self.base_data.id
|
||||
}
|
||||
|
||||
fn db_keys(&self) -> Vec<IndexKey> {
|
||||
vec![
|
||||
IndexKey {
|
||||
name: "user_id",
|
||||
value: self.user_id.to_string(),
|
||||
},
|
||||
IndexKey {
|
||||
name: "model_id",
|
||||
value: format!("{}:{}", self.model_type, self.model_id),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
56
heromodels/src/core/comment.rs
Normal file
56
heromodels/src/core/comment.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::core::model::{BaseModel, BaseModelData, IndexKey, ModelBuilder};
|
||||
use crate::impl_model_builder;
|
||||
|
||||
/// Represents a comment on a model
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Comment {
|
||||
pub base_data: BaseModelData,
|
||||
pub user_id: u32,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Comment {
|
||||
/// Create a new comment
|
||||
pub fn new(id: u32) -> Self {
|
||||
Self {
|
||||
base_data: BaseModelData::new(id),
|
||||
user_id: 0,
|
||||
content: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the user ID
|
||||
pub fn user_id(mut self, id: u32) -> Self {
|
||||
self.user_id = id;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the content
|
||||
pub fn content(mut self, content: impl ToString) -> Self {
|
||||
self.content = content.to_string();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseModel for Comment {
|
||||
fn db_prefix() -> &'static str {
|
||||
"comment"
|
||||
}
|
||||
|
||||
fn get_id(&self) -> u32 {
|
||||
self.base_data.id
|
||||
}
|
||||
|
||||
fn db_keys(&self) -> Vec<IndexKey> {
|
||||
vec![
|
||||
IndexKey {
|
||||
name: "user_id",
|
||||
value: self.user_id.to_string(),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Implement ModelBuilder for Comment
|
||||
impl_model_builder!(Comment);
|
10
heromodels/src/core/lib.rs
Normal file
10
heromodels/src/core/lib.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
pub mod model;
|
||||
pub mod comment;
|
||||
|
||||
|
||||
|
||||
// Re-export key types for convenience
|
||||
pub use model::{BaseModel, BaseModelData, IndexKey, IndexKeyBuilder, ModelBuilder};
|
||||
pub use comment::Comment;
|
||||
pub use crate::impl_model_builder;
|
7
heromodels/src/core/mod.rs
Normal file
7
heromodels/src/core/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
// Export submodules
|
||||
pub mod model;
|
||||
pub mod comment;
|
||||
|
||||
// Re-export key types for convenience
|
||||
pub use model::{BaseModel, BaseModelData, IndexKey, IndexKeyBuilder, ModelBuilder};
|
||||
pub use comment::Comment;
|
@@ -100,7 +100,7 @@ impl BaseModelData {
|
||||
/// Remove a comment from this model
|
||||
pub fn remove_comment(&mut self, comment_id: u32) {
|
||||
self.comments.retain(|&id| id != comment_id);
|
||||
self.modified_at = chrono::Utc::now().timestamp();
|
||||
self.update_modified();
|
||||
}
|
||||
|
||||
/// Update the modified timestamp
|
||||
@@ -164,11 +164,29 @@ impl BaseModelDataBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for model builders that have a base_data field
|
||||
pub trait ModelBuilder: Sized {
|
||||
/// Get a mutable reference to the base_data field
|
||||
fn base_data_mut(&mut self) -> &mut BaseModelData;
|
||||
|
||||
/// Set the ID for this model
|
||||
fn id(mut self, id: u32) -> Self {
|
||||
self.base_data_mut().id = id;
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the model, updating the modified timestamp
|
||||
fn build(mut self) -> Self {
|
||||
self.base_data_mut().update_modified();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Macro to implement BaseModel for a struct that contains a base_data field of type BaseModelData
|
||||
#[macro_export]
|
||||
macro_rules! impl_base_model {
|
||||
($type:ty, $prefix:expr) => {
|
||||
impl BaseModel for $type {
|
||||
impl $crate::core::model::BaseModel for $type {
|
||||
fn db_prefix() -> &'static str {
|
||||
$prefix
|
||||
}
|
||||
@@ -178,4 +196,16 @@ macro_rules! impl_base_model {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Macro to implement ModelBuilder for a struct that contains a base_data field of type BaseModelData
|
||||
#[macro_export]
|
||||
macro_rules! impl_model_builder {
|
||||
($type:ty) => {
|
||||
impl $crate::core::model::ModelBuilder for $type {
|
||||
fn base_data_mut(&mut self) -> &mut $crate::core::model::BaseModelData {
|
||||
&mut self.base_data
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@@ -1,47 +1,12 @@
|
||||
//! # Hero Models
|
||||
//!
|
||||
//! A library for hero models with base model trait implementation.
|
||||
//!
|
||||
//! This crate provides a base model trait and implementation that other models can inherit from.
|
||||
//! It also provides a Comment model that can be used to add comments to any model.
|
||||
// Export core module
|
||||
pub mod core;
|
||||
|
||||
pub mod model;
|
||||
pub mod comment;
|
||||
pub mod user;
|
||||
// Export userexample module
|
||||
pub mod userexample;
|
||||
|
||||
// Re-export key types for convenience
|
||||
pub use model::{BaseModel, BaseModelData, IndexKey, impl_base_model};
|
||||
pub use comment::Comment;
|
||||
pub use user::User;
|
||||
pub use core::{BaseModel, BaseModelData, IndexKey, ModelBuilder};
|
||||
pub use core::Comment;
|
||||
pub use userexample::User;
|
||||
|
||||
/// Example of how to use the heromodels crate
|
||||
///
|
||||
/// ```rust
|
||||
/// use heromodels::{BaseModel, User, Comment};
|
||||
///
|
||||
/// // Create a new user
|
||||
/// let mut user = User::new(
|
||||
/// 1,
|
||||
/// "johndoe".to_string(),
|
||||
/// "john.doe@example.com".to_string(),
|
||||
/// "John Doe".to_string()
|
||||
/// );
|
||||
///
|
||||
/// // Create a comment for the user
|
||||
/// let comment = Comment::new(
|
||||
/// 1,
|
||||
/// 2, // commenter's user ID
|
||||
/// user.get_id(),
|
||||
/// User::db_prefix().to_string(),
|
||||
/// "This is a comment on the user".to_string()
|
||||
/// );
|
||||
///
|
||||
/// // Add the comment to the user
|
||||
/// user.base_data.add_comment(comment.get_id());
|
||||
///
|
||||
/// // Get the database prefix for the User model
|
||||
/// assert_eq!(User::db_prefix(), "user");
|
||||
///
|
||||
/// // Get the database keys for the user
|
||||
/// let keys = user.db_keys();
|
||||
/// assert!(keys.iter().any(|k| k.name == "username" && k.value == "johndoe"));
|
||||
// No need to re-export macros as they are already exported at the crate root
|
6
heromodels/src/userexample/lib.rs
Normal file
6
heromodels/src/userexample/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
// Export user module
|
||||
pub mod user;
|
||||
|
||||
// Re-export User for convenience
|
||||
pub use user::User;
|
5
heromodels/src/userexample/mod.rs
Normal file
5
heromodels/src/userexample/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
// Export user module
|
||||
pub mod user;
|
||||
|
||||
// Re-export User for convenience
|
||||
pub use user::User;
|
@@ -1,5 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::model::{BaseModel, BaseModelData, IndexKey};
|
||||
use crate::core::model::{BaseModel, BaseModelData, IndexKey, ModelBuilder};
|
||||
use crate::impl_model_builder;
|
||||
|
||||
/// Represents a user in the system
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -22,38 +23,58 @@ pub struct User {
|
||||
|
||||
impl User {
|
||||
/// Create a new user
|
||||
pub fn new(id: u32, username: String, email: String, full_name: String) -> Self {
|
||||
pub fn new(id: u32) -> Self {
|
||||
Self {
|
||||
base_data: BaseModelData::new(id),
|
||||
username,
|
||||
email,
|
||||
full_name,
|
||||
username: String::new(),
|
||||
email: String::new(),
|
||||
full_name: String::new(),
|
||||
is_active: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the username
|
||||
pub fn username(mut self, username: impl ToString) -> Self {
|
||||
self.username = username.to_string();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the email
|
||||
pub fn email(mut self, email: impl ToString) -> Self {
|
||||
self.email = email.to_string();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the full name
|
||||
pub fn full_name(mut self, full_name: impl ToString) -> Self {
|
||||
self.full_name = full_name.to_string();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Set whether the user is active
|
||||
pub fn is_active(mut self, is_active: bool) -> Self {
|
||||
self.is_active = is_active;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a comment ID
|
||||
pub fn add_comment(mut self, comment_id: u32) -> Self {
|
||||
self.base_data.add_comment(comment_id);
|
||||
self
|
||||
}
|
||||
|
||||
/// Deactivate the user
|
||||
pub fn deactivate(&mut self) {
|
||||
self.is_active = false;
|
||||
self.base_data.update_modified();
|
||||
}
|
||||
|
||||
/// Activate the user
|
||||
pub fn activate(&mut self) {
|
||||
self.is_active = true;
|
||||
self.base_data.update_modified();
|
||||
}
|
||||
|
||||
/// Update user's email
|
||||
pub fn update_email(&mut self, email: String) {
|
||||
self.email = email;
|
||||
self.base_data.update_modified();
|
||||
}
|
||||
|
||||
/// Update user's full name
|
||||
pub fn update_full_name(&mut self, full_name: String) {
|
||||
self.full_name = full_name;
|
||||
self.base_data.update_modified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +104,7 @@ impl BaseModel for User {
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement ModelBuilder for User
|
||||
impl_model_builder!(User);
|
Reference in New Issue
Block a user