RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/burugo/one-mcp

Cursor rule

.cursor/rules/thing.mdc

[object Object]

Cursor rules

Quality

58/100

Scores the file, not the repository.

Length

1,156 words

8 headings · 14 code blocks

Repository

406

— · pushed 1 days ago

Last changed

3 days ago

First indexed 3 days ago.
burugo/one-mcp/.cursor/rules/thing.mdcRawGitHub
1---
2description:
3globs: *.go
4alwaysApply: false
5---
6---
7description:
8globs: *.go
9alwaysApply: false
10---
11# Rule Name: Thing ORM Usage Guide
12 
13# Description:
14# Quick reference for using the Thing ORM (github.com/burugo/thing).
15 
16## Core Concept
17- High-performance Go ORM focusing on CRUD and list operations.
18- Built-in caching (Redis or in-memory) automatically handles single-entity and list query caching & invalidation.
19- Uses Go generics for type safety and a cleaner API.
20- Supports MySQL, PostgreSQL, SQLite.
21 
22## Configuration
231. **Create DB Adapter:**
24```go
25 import "github.com/burugo/thing/drivers/db/sqlite" // Or mysql, postgres
26 dbAdapter, err := sqlite.NewSQLiteAdapter(":memory:")
27```
282. **Create Cache Client (Optional, defaults to in-memory):**
29```go
30 import (
31 "github.com/redis/go-redis/v9"
32 redisCache "github.com/burugo/thing/drivers/cache/redis"
33 "github.com/burugo/thing"
34 )
35 // Use nil for default in-memory:
36 // var cacheClient thing.CacheClient = nil
37 // Or Redis:
38 // rdb := redis.NewClient(...)
39 // cacheClient = redisCache.NewClient(rdb)
40```
413. **Get ORM Instance per Model:**
42```go
43 import "github.com/burugo/thing"
44 // import your models package
45 
46 // For a specific model typels.User)
47 userThing, err := thing.New[*models.User](mdc:db)
48```
49 *Alternative Global Config (less flexible):* `thing.Configure(dbAdapter, cacheClient)` then `thing.Use[*Model]()`.
50 
51## Basic Usage
521. **Model Definition:** Embed `thing.BaseModel` and use `db` tags for columns.
53```go
54 type User struct {
55 thing.BaseModel // Includes ID, CreatedAt, UpdatedAt, DeletedAt
56 Name string `db:"name"` // Explicitly maps Name field to 'name' column
57 UserAge int // db tag omitted, defaults to 'user_age' column
58 }
59 // Optional: Define TableName() method if different from snake_case plural struct name.
60 // func (u *User) TableName() string { return "custom_users_table" }
61```
62 **Note:** While using the `db` tag is recommended for clarity, it's technically optional. If omitted, Thing ORM defaults to converting the Go field name (CamelCase, e.g., `UserAge`) to its snake_case equivalent (`user_age`) as the database column name. Use `db:"-"` to explicitly ignore a field.
63 
64 **Example:**
65```go
66 // Example: All index types and relationships
67 type User struct {
68 thing.BaseModel
69 Name string `db:"name,index"` // Single-field index
70 Email string `db:"email,unique"` // Single-field unique index
71 ColA string `db:"col_a,index:idx_ab"` // Composite index (idx_ab)
72 ColB int `db:"col_b,index:idx_ab"` // Composite index (idx_ab)
73 KeyA string `db:"key_a,unique:uq_ab"` // Composite unique index (uq_ab)
74 KeyB string `db:"key_b,unique:uq_ab"` // Composite unique index (uq_ab)
75 // Relationship example:
76 Books []*Book `thing:"hasMany;fk:user_id;model:Book" db:"-"`
77 }
78```
79 
80 **Indexes are always declared in the db tag (index, unique, index:..., unique:...).**
81 **The thing tag is only used for relationship declarations (hasMany, belongsTo, model, fk, etc.).**
82 **Do not use thing tag for index declaration.**
832. **CRUD Operations and Querying (using `userThing` from config step):**
84 - **Create/Update:** `err := userThing.Save(&userInstance)` (creates if ID is zero, updates otherwise).
85 - **Read by ID:** `foundUser, err := userThing.ByID(id)` (uses cache).
86 - **Read Multiple by IDs:** `userMap, err := userThing.ByIDs([]int64{1, 2, 3}, "OptionalPreloadField")` (uses cache, returns `map[int64]YourModelType`. Preloading is optional).
87 - **Delete (Hard):** `err := userThing.Delete(&userInstance)`.
88 - **Soft Delete:** `err := userThing.SoftDelete(&userInstance)` (sets `deleted=true` and `updated_at`).
89 
90 - **Querying Records:**
91 The `thing` ORM provides a flexible way to build and execute queries.
92 
93 - **Initiating a Query:**
94 You can start a query using `Query()` with `thing.QueryParams` or by chaining methods like `Where()`, `Order()`, and `Preload()`. All query methods return a `*CachedResult[T]` instance, allowing for lazy execution.
95```go
96 // Option 1: Using QueryParams
97 params := thing.QueryParams{
98 Where: "age > ? AND status = ?", Args: []interface{}{25, "active"},
99 Order: "name ASC",
100 Preloads: []string{"Books"}, // For preloading relationships
101 }
102 result := userThing.Query(params)
103 
104 // Option 2: Chainable methods (can be started from userThing or chained on a CachedResult)
105 // Starting from userThing:
106 result = userThing.Where("age > ?", 25).Order("name ASC").Preload("Books")
107 // Chaining on an existing result:
108 // result = existingResult.Where("status = ?", "active")
109```
110 
111 - **Fetching Results from `CachedResult[T]`:**
112 Once you have a `CachedResult[T]`, you can fetch data in various ways:
113```go
114 // Fetch a paginated list (e.g., offset 0, limit 10)
115 users, err := result.Fetch(0, 10) // Uses cache
116 
117 // Fetch the first record matching the query
118 // Returns common.ErrNotFound if no record matches
119 firstUser, err := result.First()
120 if err != nil {
121 if errors.Is(err, common.ErrNotFound) {
122 // Handle case where no user was found
123 } else {
124 // Handle other errors
125 }
126 }
127 
128 // Fetch all records matching the query
129 allMatchingUsers, err := result.All()
130```
131 
132 - **Counting Records:**
133 To get the total number of records matching the query conditions:
134```go
135 count, err := result.Count() // Uses cache
136```
137 
138 - **Including Soft-Deleted Records:**
139 By default, queries exclude soft-deleted records. To include them, use `WithDeleted()` on a `CachedResult[T]`:
140```go
141 resultIncludingDeleted := result.WithDeleted()
142 // Now, Fetch(), First(), All(), Count() on resultIncludingDeleted will include soft-deleted items.
143 // Example:
144 // usersIncludingDeleted, err := resultIncludingDeleted.Fetch(0, 10)
145```
146
147 - **Fetching All Records of a Model (Simplified):**
148 To get all records for a model type without any specific query conditions:
149```go
150 allUsersOfType, err := userThing.All()
151 // This is a convenient alias for userThing.Query(thing.QueryParams{}).All()
152```
153 
154## Key Features
155- **Caching:** Mostly automatic for `ByID` and `Query`. Monitor via `cacheClient.GetCacheStats(ctx)`.
156- **Relationships:** Define using `thing` struct tags (`hasMany`, `belongsTo`, `manyToMany`) and preload using `QueryParams.Preloads`. Always use `db:"-"` on relation fields in your struct, as these fields are populated by the ORM and do not correspond directly to a column in the model's own table.
157 
158 - **`hasMany`**: One-to-many relationship.
159```go
160 // User has many Books.
161 // Assumes 'books' table has a 'user_id' foreign key.
162 type User struct {
163 thing.BaseModel
164 // ... other fields
165 Books []*Book `thing:"hasMany;fk:user_id;model:Book" db:"-"`
166 }
167 
168 type Book struct {
169 thing.BaseModel
170 UserID uint `db:"user_id"` // Foreign key
171 Title string `db:"title"`
172 // ... other fields
173 }
174```
175 
176 - **`belongsTo`**: Inverse of one-to-many.
177```go
178 // Book belongs to a User.
179 // Assumes 'books' table has a 'user_id' foreign key.
180 type Book struct {
181 thing.BaseModel
182 UserID uint `db:"user_id"` // Foreign key
183 Title string `db:"title"`
184 User *User `thing:"belongsTo;fk:user_id;model:User" db:"-"` // 'model' is optional here if type matches
185 // ... other fields
186 }
187 
188 type User struct {
189 thing.BaseModel
190 Name string `db:"name"`
191 // ... other fields
192 }
193```
194 
195 - **`manyToMany`**: Many-to-many relationship.
196 Requires a join table.
197```go
198 // User has and belongs to many Roles.
199 // Roles has and belongs to many Users.
200 // Join table: 'user_roles' with 'user_id' (links to users.id) and 'role_id' (links to roles.id).
201 type User struct {
202 thing.BaseModel
203 Name string `db:"name"`
204 Roles []*Role `thing:"manyToMany;model:Role;joinTable:user_roles;joinLocalKey:user_id;joinRelatedKey:role_id" db:"-"`
205 // ... other fields
206 }
207 
208 type Role struct {
209 thing.BaseModel
210 Name string `db:"name"`
211 Users []*User `thing:"manyToMany;model:User;joinTable:user_roles;joinLocalKey:role_id;joinRelatedKey:user_id" db:"-"`
212 // ... other fields
213 }
214 
215 // Join table model (optional to define as a struct, but table must exist)
216 // type UserRole struct {
217 // UserID uint `db:"user_id"`
218 // RoleID uint `db:"role_id"`
219 // }
220 // func (ur *UserRole) TableName() string { return "user_roles" }
221```
222 Preloading relationships:
223```go
224 // Preload Books for a User
225 // users, err := userThing.Query(thing.QueryParams{Preloads: []string{"Books"}}).Fetch(0,10)
226 
227 // Preload Roles for a User (manyToMany)
228 // users, err := userThing.Query(thing.QueryParams{Preloads: []string{"Roles"}}).Fetch(0,10)
229```
230- **Hooks:** Register listeners for events (e.g., `BeforeSave`, `AfterCreate`) using `thing.RegisterListener`.
231- **Auto Migration:** `thing.AutoMigrate(&User{}, &Book{})` creates/updates tables based on model struct tags (`db`).
232- **JSON Serialization:** `thing.ToJSON(model, options...)`. Use `thing.WithFields("field1,nested{subfield},-excluded")` for flexible control, including method-based virtual properties (e.g., `FullName() string` -> `full_name` in DSL).
233- **Raw SQL:** Access via `dbAdapter := userThing.DBAdapter()`, then use `dbAdapter.Exec`, `dbAdapter.Get`, `dbAdapter.Select`.
234 
235## Focus
236- Optimized for common CRUD and list retrieval patterns.
237- Complex JOINs or database-specific features might require Raw SQL.

Sections

  • Rule Name: Thing ORM Usage Guide
  • Description:
  • Quick reference for using the Thing ORM (github.com/burugo/thing).
  • Core Concept
  • Configuration
  • Basic Usage
  • Key Features
  • Focus

What it covers

code-styledatabase

Stack — with the evidence

go

(1.00)

docker

(1.00)

node

(0.70)

react

(0.70)

tailwind

(0.70)

vite

(0.70)

vitest

(0.70)

playwright

(0.70)

eslint

(0.70)

typescript

(0.60)

github-actions

(0.60)

javascript

(0.50)

Glob targeting

  • *.go

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
burugo
Language
—
License
—
Archived
no

All configs in this repo

Also in burugo/one-mcp

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
burugo/one-mcp.cursor/rules/language.mdc · 406Cursor rulesgodocker+10git4/1003 days ago
burugo/one-mcp.cursor/rules/tdd.mdc · 406Cursor rulesgodocker+10testlint-formattesting-strategyapi+189/1003 days ago
burugo/one-mcpAGENTS.md · 406AGENTS.mdgodocker+10setupbuildtestlint-format+479/1003 days ago
Diff against .cursor/rules/language.mdc Diff against .cursor/rules/tdd.mdc Diff against AGENTS.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack