Ah, documentation. Except for some time on my bike, I've spent all day doing presentation slides and Model-Glue 2.0 documentation. Not the most fun part of my life, but I'll be starting a new development project tomorrow, so I need to get it taken care of.
Anyhow, when documenting the generic database and scaffolding portions, I thought some people might like some extra insight into how "scaffolding" really works. It's very easy to picture it as one big monolith of code that has little do to with the partitions of MVC, but the internals follow a pretty good separation of concerns, leaving the API pretty easy to use from inside your own event handlers and even controllers.
Lowest Level: The ORM Adapter
The ORM adapter is sort of the "core" of scaffolding. It's a pretty straightforward interface that defines methods like new() (used to create a new instance of an object), save() (pretty self explanatory), list() (does a query), etc.
Inside of the ORM-framework specific implementation adapter, the intent (do a generic read of Widget where WidgetId = 2) is translated into framework-specific code (Reactor.createDAO("Widget").read(widgetId=2)).
Why's that good to know? Well, you can use the ORM adapter from inside any of your controllers by asking the framework for it:
<cfset orm = getModelGlue().getORMAdapter() />
That way, you can quickly invoke gateway methods to retrieve lists, do CRUD operations without writing ORM-framework specific code, and even get back the same metadata about properties and relationships that's used to generate the scaffold HTML.
Second Level: The ORMController
Scaffolds are really nothing but Model-Glue events that predefine some message broadcasts and results. These message broadcasts are known as the "Generic Database Messages" (GDMs) and include messages like ModelGlue.genericList (lists records from a table). The full list, and their behavior, is available in the Model-Glue documentation.
These messages are "listened for" just like any other message: there's a controller, called the ORMController, that's automatically loaded when the framework starts. It's just got the code-level equivalent of a few <message-listener> tags that set it up to "hear" these messages.
When it "hears" one of the GDM's, it gets the ORM adapter and calls the appropriate method on it, passing along whatever event values are appropriate.
It's not a really complicated setup.
Third Level: "Scaffolds" themselves
When your ModelGlue.xml file is read, it parses any tags inside of an <event-handlers> block, passing them off to something known as the EventHandlerFactory. A basic, vanilla event-handler tag results in the creation of an EventHandler CFC instance. A scaffold tag, however, results in the creation of multiple subclasses of EventHandler, representing the different types (such as list, commit, etc.) of scaffolds to be created. When the "scaffold" event-handler is created, it creates any necessary .CFM views via an XSL transformation, and adds appropriate message broadcasts, results, and views to itself.
After the framework loads all of the event-handlers, any that identify themselves are then "compiled" down to their basic Model-Glue XML and written out to /config/scaffolds/Scaffolds.xml - if you open it up, you'll see that they really are nothing but regular event-handlers with views ("V") that make use of the generic database messages, which are listened for by the ORMController ("C"), which then hand values off to the business tier of the ORMAdapter ("M").
And that's how Model-Glue does scaffolding while retaining the loose coupling of MVC!
1 comments - Posted by Joe Rinehart at 4:54 PM - Categories: Model-Glue