@@ -173,6 +173,25 @@ npx @apidevtools/swagger-cli validate openapi.json
173173> - SeaORM relation support (HasOne, BelongsTo, HasMany)
174174> - No manual field synchronization
175175
176+ ### Best Practices
177+
178+ | DO | DON'T |
179+ | ----| -------|
180+ | Use ` pick ` to select only needed fields | Define manual structs that duplicate Model fields |
181+ | Use ` omit ` to exclude sensitive fields | Use ` name ` parameter unnecessarily |
182+ | Use full ` crate::models::... ` paths | Rely on implicit module resolution |
183+ | Define schema near route handlers | Scatter schemas across unrelated files |
184+
185+ ** Primary Parameters (USE THESE):**
186+ - ` pick = [...] ` - Allowlist: include ONLY these fields
187+ - ` omit = [...] ` - Denylist: exclude these fields
188+
189+ ** Advanced Parameters (USE SPARINGLY):**
190+ - ` partial ` - For PATCH endpoints only
191+ - ` rename ` - Only when API naming differs from model
192+ - ` add ` - Only when truly new fields needed (breaks ` From ` impl)
193+ - ` name ` - ** AVOID** unless same-file Model reference (see below)
194+
176195### Why Not Manual Structs?
177196
178197``` rust
@@ -223,9 +242,12 @@ schema_type!(InternalDTO from Model, ignore);
223242schema_type! (LargeResponse from SomeType , clone = false );
224243```
225244
226- ### Same-File Model Reference
245+ ### Same-File Model Reference (When to Use ` name ` )
246+
247+ > ** The ` name ` parameter is ONLY needed for same-file Model references.**
248+ > For cross-file references, use full paths and descriptive struct names instead.
227249
228- When the model is in the same file, use simple name with ` name ` parameter :
250+ When defining Schema in the same file as Model (common for SeaORM entities) :
229251
230252``` rust
231253// In src/models/user.rs
@@ -237,10 +259,20 @@ pub struct Model {
237259
238260pub enum UserStatus { Active , Inactive }
239261
240- // Simple `Model` path works - module path inferred from file location
262+ // ✅ CORRECT: Same-file reference - use `name` for OpenAPI schema name
241263vespera :: schema_type! (Schema from Model , name = " UserSchema" );
264+
265+ // ❌ WRONG: Using `name` for cross-file reference
266+ // schema_type!(Schema from crate::models::user::Model, name = "UserResponse");
267+ // ✅ CORRECT: Use descriptive struct name instead
268+ // schema_type!(UserResponse from crate::models::user::Model, omit = ["password"]);
242269```
243270
271+ ** Why avoid ` name ` for cross-file references?**
272+ - The struct name itself becomes the OpenAPI schema name
273+ - ` UserResponse ` is clearer than ` Schema ` with ` name = "UserResponse" `
274+ - Less parameters = less complexity
275+
244276### Cross-File References
245277
246278Reference structs from other files using full module paths:
@@ -281,17 +313,29 @@ Json(model.into()) // Easy conversion!
281313
282314### Parameters
283315
316+ ** Recommended (Primary):**
317+
284318| Parameter | Description | Example |
285319| -----------| -------------| ---------|
286320| ` pick ` | Include only these fields | ` pick = ["name", "email"] ` |
287321| ` omit ` | Exclude these fields | ` omit = ["password"] ` |
288- | ` rename ` | Rename fields | ` rename = [("id", "user_id")] ` |
289- | ` add ` | Add new fields (disables From impl) | ` add = [("extra": String)] ` |
290- | ` partial ` | Make fields optional for PATCH | ` partial ` or ` partial = ["name"] ` |
291- | ` name ` | Custom OpenAPI schema name | ` name = "UserSchema" ` |
292- | ` rename_all ` | Serde rename strategy | ` rename_all = "camelCase" ` |
293- | ` ignore ` | Skip Schema derive | bare keyword |
294- | ` clone ` | Control Clone derive (default: true) | ` clone = false ` |
322+
323+ ** Situational (Use When Needed):**
324+
325+ | Parameter | Description | When to Use |
326+ | -----------| -------------| -------------|
327+ | ` partial ` | Make fields optional | PATCH endpoints only |
328+ | ` rename ` | Rename fields | API naming differs from model |
329+ | ` rename_all ` | Serde rename strategy | Different casing needed |
330+ | ` add ` | Add new fields | New fields not in model (breaks ` From ` impl) |
331+
332+ ** Avoid (Special Cases Only):**
333+
334+ | Parameter | Description | When to Use |
335+ | -----------| -------------| -------------|
336+ | ` name ` | Custom OpenAPI schema name | ** Same-file Model reference only** |
337+ | ` ignore ` | Skip Schema derive | Internal DTOs not for OpenAPI |
338+ | ` clone ` | Control Clone derive | Large structs where Clone is expensive |
295339
296340### SeaORM Integration (RECOMMENDED)
297341
@@ -334,7 +378,9 @@ vespera::schema_type!(Schema from Model, name = "MemoSchema");
334378### Complete Example
335379
336380``` rust
337- // src/models/user.rs (Sea-ORM entity)
381+ // ============================================
382+ // src/models/user.rs (SeaORM entity)
383+ // ============================================
338384#[derive(Clone , Debug , DeriveEntityModel , Serialize , Deserialize )]
339385#[sea_orm(table_name = " users" )]
340386pub struct Model {
@@ -347,10 +393,16 @@ pub struct Model {
347393 pub created_at : DateTimeWithTimeZone ,
348394}
349395
350- // Generate Schema in same file - simple Model path
396+ // ✅ Same-file: use `name` parameter for OpenAPI schema name
351397vespera :: schema_type! (Schema from Model , name = " UserSchema" );
352398
353- // src/routes/users.rs - use full path for cross-file reference
399+ // ============================================
400+ // src/routes/users.rs (Route handlers)
401+ // ============================================
402+ use vespera :: schema_type;
403+
404+ // ✅ Cross-file: use descriptive struct names + pick/omit
405+ // NO `name` parameter needed - struct name = OpenAPI schema name
354406schema_type! (CreateUserRequest from crate :: models :: user :: Model , pick = [" name" , " email" ]);
355407schema_type! (UserResponse from crate :: models :: user :: Model , omit = [" password_hash" ]);
356408schema_type! (UserPatch from crate :: models :: user :: Model , omit = [" password_hash" , " id" ], partial );
@@ -370,6 +422,22 @@ pub async fn patch_user(
370422}
371423```
372424
425+ ### Quick Reference
426+
427+ ``` rust
428+ // ✅ RECOMMENDED PATTERNS
429+ schema_type! (CreateUserRequest from crate :: models :: user :: Model , pick = [" name" , " email" ]);
430+ schema_type! (UserResponse from crate :: models :: user :: Model , omit = [" password_hash" ]);
431+ schema_type! (UserListItem from crate :: models :: user :: Model , pick = [" id" , " name" ]);
432+
433+ // ⚠️ USE SPARINGLY
434+ schema_type! (UserPatch from crate :: models :: user :: Model , partial ); // PATCH only
435+ schema_type! (Schema from Model , name = " UserSchema" ); // Same-file only
436+
437+ // ❌ AVOID
438+ schema_type! (Schema from crate :: models :: user :: Model , name = " UserResponse" ); // Use struct name!
439+ ```
440+
373441---
374442
375443## Merging Multiple Vespera Apps
0 commit comments