MVC in Appcelerator

Regardless of if you actually plan on delivering two distinct apps (normal and HD) or not, you’ll want to architect your application in such a way that you can maximize the sharing of code.  This means using Object-oriented Javascript and a true MVC (Model-View-Controller) paradigm in your code organization.

First we’ll start off with app organization. This seems simple, but it isn’t.

The first thing an Appcelerator app does when loading your app is to run “app.js”.  So our app.js looks something like this:

1
2
3
4
5
var window = Ti.UI.createWindow(
{
  url: "views/main.js"
});
window.open();

What this does is open up a new window, with a new execution context in the views/main.js file.  This is great, because when we include further javascript files, they will all be loaded from the 2nd-level directory (i.e. views, controllers, include, etc.).  If we had stayed within the first execution context, we wouldn’t have been able to organize our files so nicely, since everything would have to be loaded from the base directory. You can read more on execution contexts here.

Object-oriented Architecture

In modern programming app design, we want to write and maintain as little code as possible, which means re-using code wherever possible.  In order to do this with Appcelerator, we need to use good inheritance and OO design principles.

First, we should create a base controller and view class. This uses a custom inheritance scheme by John Resig .

common/controller.js

1
2
3
4
5
6
7
8
9
Ti.include("../include/inheritance.js");
 
var Controller = Class.extend({
    init: function(win)
    {
        this.win = win;
        win.controllerClass = this;
    }
});


common/view.js

1
2
3
4
5
6
7
8
9
10
11
Ti.include("../include/inheritance.js");
 
var View = Class.extend({
    init: function(win, controller)
    {
        this.win = win;
        this.controller = controller;
 
        win.viewClass = this;
    }
});

Now, we can create our real controllers and views:

controllers/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Ti.include("../include/inheritance.js");
Ti.include("../include/db.js");
Ti.include("../common/controller.js");
Ti.include("../views/main.js");
 
var MainController = Controller.extend({
    init: function(win) {
        this._super(win);
 
        // Create the view for this controller
        this.view = new MainView(win, this);
    }
});
 
(function() {
    var win = Titanium.UI.currentWindow;
 
    // Create our controller for this window.
    new MainController(win);
})();

As you can see, now we’ve got a main controller, which also instantiates a view.   Now, the view can handle all layout code, and the controller can respond to those events, and affect the view appropriately.  This works especially well when designing Universal Apps, as we can Design two views, a iPhoneMainView, and iPadMainView, and instantiate the appropriate one.

Now for the view code:
controllers/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Ti.include("../include/inheritance.js");
Ti.include("../include/db.js");
Ti.include("../common/view.js");
 
var MainView = View.extend({
    init: function(win, controller) {
        this._super(win, controller);
 
        this.layout();
    },
 
    layout: function() {
       // Your layout code.  Ti.UI.createLabel({}), etc.;
    }
 
});

I’ve created a Github project called Appcelerator-On-Rails to show this code. I use this template in all my Appcelerator projects and add to it when necessary.

Happy iPhone coding!

Rails CMS plugins

I’m currently working on a project that requires a built-in CMS solution to enable quick SEO and content modification by site administrators.  This is not an uncommon problem – pretty much every website requires content management, and it amazes me that Rails doesn’t come with something pre-built (OK, there are those that argue that Rails is a CMS, but there sure seems to be a lot of work involved in getting it there).  On the other hand, I can see why Rails doesn’t include a CMS, as it’s meant as a web framework, not a website framework.

There are several great CMS systems for Rails out there (check out this overview) – but Comatose, Radiant and Refinery are the front-runners.  Your options for integrating a CMS system into Rails pretty much fall into 3 categories [1]:

  1. Two side-by-side applications. – Pair an off-the-shelf CMS with a custom built application. Copy/paste the visual elements, and loosely wire the two together with a subdomain or some kind of web proxy to share the URL structure
  2. Extend the CMS – Build a proprietary plugin or extension for the CMS to implement the application features.
  3. Soup-to-nuts custom application. Build a complete CMS as part of the project.
  4. Use a Rails plugin CMS.

For an in depth look at the problem posed by existing Rails CMS solutions, check out this article (and thanks Aaron for the quote above).  The first option is not a great solution, as there is a lot of re-work and duplication, not to mention the potential for screw-ups (oops! who forgot to update the price list??).  #2 is a terrible idea because you’re stuck to the CMS you begin with, and #3 is plain wasteful.  #4 is definitely the best option, as it’s completely modular and does not interfere with your code business logic.

Comatose and Refinery both fall into the 4th and best option – Rails plugins. After looking at Comatose, it seemed that it was a bit simplistic for my needs (and it hasn’t been updated since 2008).  Refinery was much better, but still lacking in some areas.  My issue with Refinery is that you still have to hand-code a theme for the site, which makes it very difficult to separate the design from the implementation (especially if you want a web designer to make any of the changes for you).  And adding any new features or layouts requires intervention on the side of the programmer, not the designer. But the plugin-based system definitely offered some advantages, namely that I could code my regular Rails controllers and views as I normally would.

And that left Radiant, the 800-pound gorilla in the Rails CMS world.  Radiant is definitely the most mature Rails CMS out there, and its lengthy feature-set shows: its layout mechanism is beautiful to use via radiant XML tags, and its extensions mechanism makes it easy to add custom functionality. To this end, it’s possible for a non-technical person to completely change the look of a site without touching a line of code.

However, it suffers from problem #2 outlined above – you have to extend Radiant, Radiant does not extend Rails.  This basically means that you need to code a custom extension to implement any of your business logic, which to me is highly unacceptable.

In the end, I chose to have my cake and eat it too – I hacked Radiant to make it behave like a plugin.  My recommendation for a Rails CMS?  If you’re in the market for a simple CMS with not a lot of custom application functionality, then Refinery is your best bet.

Enhanced by Zemanta

WordPress Themes