CFWheels make the database simple
I am working on porting Litepost to Wheels. Wheels had a Litepost competition awhile ago but didn't follow the Litepost comparison idea.
Litepost was conceived to compare different frameworks using essentially the same code. Once done, you will be able to compare how the same app is done in ColdBox, Fusebox, FW/1, Mach-II, Model-Glue, and Wheels.
I am wanted to quick show how the Wheels Object Relational Mapper makes database calls very simple and intuitive.
Here is the \Models\Category.cfc
<cfcomponent extends="Model" output="false">
<cffunction name="init">
<cfset property(name="id", column="categoryid")>
<cfset property(name="categoriesCount", sql="(SELECT COUNT(*) FROM entries WHERE categories.categoryid = entries.categoryId)")>
<cfset validatesPresenceOf(properties="category")>
<cfset belongsTo("Entry")>
</cffunction>
</cfcomponent>
See how everything about the Categories table is self contained and self documenting?
Wheels is even smart enough with Wheels conventions to realize the table name for \Models\Category.cfc is categories.
The first properties() function is renaming a column into something more in-line with the Wheels conventions. It adds an "AS id" to the sql for the categoryid column. No more inconsistent sql commands :-)
The second property is a really wicked trick called Calculated Properties. Thanks to Raul for showing me how to do it. It is actually doing a count of all the entries matching a categoryid. Now when the category model is called like <cfset categories = model('category').findAll() /> in the controller, it will have a new column called categoriesCount with the count.
The next function validatesPresenceOf() is actually part of Wheels built in Object Validation.
Another cool feature of the Wheels ORM is the deleteEntry action in the \Controller\Blog.cfc. Look no sql and the command will delete all the associated comments, then delete the actual entry.
aEntry = model("entry").findByKey( id );
aEntry.deleteAllComments();
aEntry.delete();
How does it know to create a deleteAllComments() function on the aEntry object? It was told in the \Models\Entry.cfc with a hasMany association.
<cfcomponent extends="Model" output="false">
<cffunction name="init">
<cfset property(name="id", column="entryid")>
<cfset validatesPresenceOf(properties="title,body")>
<cfset hasMany("comments")>
<cfset hasOne("category")>
</cffunction>
</cfcomponent>
I could even create a Callback so when a delete of an Entry anywhere, it automatically deletes any related comments.




Posted under: 


Nice write-up, Mike. Looking forward to seeing the finished project.
I'd definitely move aEntry.deleteAllComments() into an afterDelete() callback in the model. Fat model, skinny controller = keep all of the business logic in the model. :)
Cool stuff. I'm working on a CFWheels app and the calculated properties feature will come in very handy!
Yeah, I will probably move the deleteAllComments to a callback when I refactor it after the Wheels example is working. That is another great feature of Wheels. Refactoring is easy.