You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use this skill when building Active Record-style ORM models in ColdBox/BoxLang with Quick. Covers entity definition, CRUD operations, relationships (hasOne, hasMany, belongsTo, belongsToMany), query scopes, eager loading, accessors/mutators, global scopes, lifecycle hooks, and production patterns for service-layer data access.
applyTo
**/*.{bx,cfc,cfm,bxm}
Quick Skill
When to Use This Skill
Load this skill when:
Building data models using the Active Record pattern
Defining and traversing entity relationships (hasOne, hasMany, belongsTo, belongsToMany)
Writing reusable query scopes on entities
Eager-loading related data to prevent N+1 queries
Using lifecycle hooks (before/after create/save/delete)
Installation
box install quick
Quick requires qb — install both:
box install quick,qb
Entity Definition
// models/entities/User.bxclassextends="quick.models.BaseEntity"table="users"{// Explicitly list fillable columns (prevents mass-assignment vulnerability)variables._fillable=["firstName","lastName","email","role"];// Columns never returned in serialization (even if requested)variables._hidden=["password","rememberToken"];// Cast column types automaticallyvariables._casts={isActive : "boolean",preferences : "json",createdAt : "datetime"};// ---- Relationships ----// User HAS MANY Postsfunctionposts(){returnhasMany("Post")}// User HAS ONE Profilefunctionprofile(){returnhasOne("Profile")}// User BELONGS TO Role entityfunctionroleEntity(){returnbelongsTo("Role","role")}// User BELONGS TO MANY Permissions (pivot)functionpermissions(){returnbelongsToMany("Permission","user_permissions")}// ---- Scopes ----functionscopeActive(qb){qb.where("isActive",true)}functionscopeAdmins(qb){qb.where("role","admin")}functionscopeSearch(qb,term){qb.where(function(q){q.where("firstName","like","%#term#%").orWhere("lastName","like","%#term#%").orWhere("email","like","%#term#%")})}// ---- Accessors / Mutators ----// Computed property: fullNamefunctiongetFullNameAttribute(){returntrim(getFirstName()&" "&getLastName())}// Hash password on setfunctionsetPasswordAttribute(value){returnbcrypt.hashPassword(value)}}
CRUD Operations
// Inject entity (WireBox ID = entity class name)propertyname="userEntity"inject="User@quick";// Createvaruser=userEntity.create({firstName : "Alice",lastName : "Smith",email : "alice@example.com",password : "secret"// triggers setPasswordAttribute mutator})// Find by PKvaruser=userEntity.find(rc.id)// returns null if not foundvaruser=userEntity.findOrFail(rc.id)// throws EntityNotFound// Find by attributevaruser=userEntity.where("email",rc.email).first()// Updateuser.update({firstName: "Alice",lastName: "Johnson"})// Fill + saveuser.fill(rc)user.save()// Deleteuser.delete()// Soft delete (requires deletedAt column)user.softDelete()user.restore()
Querying
// All active users, newest firstvarusers=userEntity.active()// scope.orderByDesc("createdAt").limit(25).get()// Searchvarusers=userEntity.search(rc.term).get()// Adminsvaradmins=userEntity.admins().get()// Countvartotal=userEntity.active().count()// Paginatevarusers=userEntity.active().paginate(rc.page ?: 1,25)// returns { data: [], total: n, perPage: 25, currentPage: n, lastPage: n }
Relationships
// Access related entityvarposts=user.posts().get()// hasManyvarprofile=user.profile().first()// hasOnevarperms=user.permissions().get()// belongsToMany// Create through relationshipvarpost=user.posts().create({title: "Hello World",body: rc.body})// Attach/detach pivotuser.permissions().attach(permissionId)user.permissions().detach(permissionId)user.permissions().sync(permissionIds)
Eager Loading (Prevent N+1)
// Without eager loading — N+1 queries for postsvarusers=userEntity.all()for(uinusers){writeDump(u.posts().get())// query per user!}// With eager loading — 2 queries totalvarusers=userEntity.with("posts").get()varusers=userEntity.with(["posts","profile","permissions"]).get()// Nested eager loadingvarusers=userEntity.with("posts.comments").get()
Lifecycle Hooks
classextends="quick.models.BaseEntity"{functionbeforeCreate(entity){entity.setCreatedAt(now())}functionafterCreate(entity){welcomeEmailJob.setUserId(entity.getId()).dispatch()}functionbeforeDelete(entity){// Log the deletion for audit trailauditService.logDelete("User",entity.getId())}}
Legacy ORM Coverage (Merged from former orm/quick-orm)
Language Mode Reference
Concept
BoxLang (.bx)
CFML (.cfc)
Class declaration
class [extends="..."] {
component [extends="..."] {
DI annotation
@inject + property
property ... inject="...";
Extended Relationship Coverage
class extends="quick.models.BaseEntity" {
function posts() { return hasMany( "Post" ) }
function role() { return belongsTo( "Role" ) }
function profile() { return hasOne( "Profile" ) }
function teams() { return belongsToMany( "Team" ) }
function countryUsers() { return hasManyThrough( [ "Country", "State" ] ) }
}