KnockoutJS Starter - A Review

A few weeks back, Packt Publishing contacted me about reviewing one of their new titles, KnockoutJS Starter. Now, I'm in the middle of two contracts, plus my day job, and the holidays right now, so the idea of a "quick review" wasn't all that appealing. That said, I was interested in the material, and this is one of a new "Starter" line of books that Packt has started publishing. Basically small, quick primers that get you up and running with something new.

So, here's the "quick review". KnockoutJS Starter is by Eric M. Barnard. My e-book copy says it's 69 pages long, but the first 12 are the TOC, credits, and format info, so you take out the resources in the back of the book too and you're talking about 55 pages of meat. And there is meat.

The "Starter" books kind of come off as a printed blog series, sometimes, but Eric has done a pretty good job here, for the most part. The first half of the book takes you through installing the files, and setting up a quick sample app to take and edit inventory information. Now, it's all client side, with no data to start with, but line for line copy of the code will get you working. And, it was pretty slick how KnockoutJS ties data and interface together fairly seamlessly. And Eric explains how those connections are made very well.

While the base example, in the beginning of the book, is pretty straight forward, the second half could use some help. The second half goes beyond the basics, trying to describe Subscribables, Observables, and Bindings and Handlers. I was able to get through it, having some prior knowledge conceptually, but some of it is still confusing. The right idea was there, but the execution could use some polish and follow-up.

Ultimately, it was still a good introduction to KnockoutJS. If you aren't familiar with the library, I would take a good look at Eric and Packt's "Starter" book, and dive right in.

Mura Shared ORM Model - A Follow-Up

So, in my last post I talked about setting up a shared ORM model within Mura CMS. But, you always find the kicker after-the-fact. Mine's not a biggie though. I had setup a CF mapping to myModel

view plain print about
1<cfset this.mappings["/myModel"] = variables.mapPrefix & variables.BaseDir & "/mySite/includes/themes/mySite/model">

Turns out this wasn't the best location. I was pushing to the themes directory, because that was what the client wanted ("What the client wants....") Sometimes, you find a valid reason to deviate.

The Mura {site}/includes folder has it's own Application.cfc, with this wonderful tidbit of code in it:

view plain print about
1<cfif not listFindNoCase("styles.js.cfm,templates.js.cfm,editor.css.cfm,default.js.cfm,config.js.cfm",listLast(cgi.SCRIPT_NAME,"/"))>
2        <cfoutput>Access Restricted.</cfoutput>
3        <cfabort>
4        </cfif>

Now, most of the time this won't matter to you. Until you need to hit a remote method, of your model, for an Ajax request. Then...well, you see what happens. Now, you could probably change the Application.cfc, but I don't know if Mura won't overwrite this file on some future update, so it's better to just move my model into my {site} directory, as a sibling of the includes folder.

Creating a shared ORM model in Mura CMS

So, I'm working a new project, and using Mura CMS. We decided to write our modules as plugins, and are using the MuraFW/1 plugin template to do so. Thing is, each plugin really needs to share a common model that uses ColdFusion's ORM.

The MuraFW/1 plugin template has facility for defining a cfclocation for ORM configuration, but that location is relative to the plugin itself, so this took a little hunting. Finally, what made the most sense was to define ORM for the Mura site (as a whole), and let that definition propogate down to the plugins.

For those who are unfamiliar with Mura, it's a very nice CMS, and very extensible, but incredibly undocumented. There is some documentation, but it's spotty, and there are articles on their site that are quite dated. (I know this is something they are working on, so I'll leave it at that.) Luckily, I do write code for a living, so I just started pulling on strings until I found the thread I needed.

The MuraFW/1 template's application.cfc includes the core application settings:

view plain print about
1include '../../config/applicationSettings.cfm';

That works to our advantage, as anything defined in the core app then becomes available to the plugin. Looking at that file, I started looking for anything related to ORM. The first bit I came upon showed me this:

view plain print about
1<cfset this.ormenabled = properties.getProperty("ormenabled","true") />

From there, I had to figure out where ormenabled would come from. I discovered that all of those properties are defined in the /config/settings.ini.cfm file. So, if I added the right properties, I should have my orm configuration. Here is a list of the properties supported by the applicationSettings.cfm at this time:

  • ormenabled
  • ormdbcreate
  • ormcfclocation
  • ormflushAtRequestEnd
  • ormeventhandling
  • ormautomanageSession
  • ormsavemapping
  • ormskipCFCwitherror
  • ormuseDBforMapping
  • ormautogenmap
  • ormlogsql

So, knowing this, I started looking at my model. First, I placed the model in my theme:

/mysite/includes/themes/mysite/model

This was a requirement of the client, so that was ok for me. Except now, I needed a reference to that directory. A mapping. Mura allows custom CF mappings, by making changes to the /config/mappings.cfm file:

view plain print about
1<cfset this.mappings["/myModel"] = variables.mapPrefix & variables.BaseDir & "/mysite/includes/themes/mysite/model">

Now that I had my mapping, I needed to setup the ORM settings in that settings.ini.cfm file:

view plain print about
1ormenabled=true
2ormcfclocation=/myModel
3ormflushAtRequestEnd=false
4ormautomanageSession=false
5ormeventhandling=true

The only thing I was missing was my ORM Event Handler. While the settings allowed me to enable ormeventhandling, they did not allow me to define the handler. For that, I added the setting in my plugin Application.cfc files, right after the initial includes:

view plain print about
1this.ormsettings.eventhandler = "myModel.aop.GlobalEventHandler";

I reloaded my application, then updated my plugins (in the Mura Plugin admin) for good measure. Presto! Shared ORM! Hopefully this will help others from spinning their wheels.

Side Note: During this process, I also updated to the Mura v6 Preview. Wow! What an improvement. And the Bootstrap usage should make layout and theming much easier.