-
Notifications
You must be signed in to change notification settings - Fork 120
Tower Beginner's Guide
Tower is a Javascript framework for building real-time web apps. It is a full featured MVC framework, similar to Rails except built on the Node ecosystem. This means it’s incredibly fast, asynchronous (multi-tasking) and made for the browser. Literally everything in Tower uses Javascript! From the database which stores data as JSON, to the Node.js web server, to the template, and of course the Javascript client side.
In this guide we are going to be creating a very simple blog. There will be no test driven development or Git commits here as this can be a barrier to learning the unique concepts of Node and Tower.
Use Homebrew to install the following:
- Node (brew install node) - This also installs Node's package manager: NPM
- Git (brew install git
Mac users may be asked by Homebrew to install GCC. First install Xcode through the App Store, and then in Xcode preferences install ‘Command Line Tools’ under ‘Downloads’.
Node is new, and Tower is even newer. So you will likely experience errors. They are either due to your OS version, 3rd party libraries, or whether or not you have installed every Node package required by Tower.
Unfortunately Node errors are a bit cryptic. The best way to debug is by Googling the error in hopes that someone else has already asked about it. Common errors will be noted as we go along.
First we need to generate the default application files:
- Run
tower new <app-name>
in the Terminal. - Move into the directory
cd <app-name>
- This has generated a basic application shell, but we still need to download node packages specific to this install with
npm install
- Make sure your database is running with
mongod
- And then start the server with
node server
One last thing. You will be writing your app in CoffeeScript, a language which abstracts common Javascript conventions. CoffeeScript is similar in appearance to Ruby. In the Node and Browser world though, CoffeeScript will allow us to write callback driven, asynchronous code.
Tower compiles source files as you develop into Javascript, CSS and HTML. This is a process that must be run while developing. In a new window type:
cd path/to/<app-name>
cake watch
A resource is a set of Models, Views and Controllers that manage a particular thing. Our simple blog will consist of 2 resources, Posts and Comments.
Open up the Terminal and execute the following commands to create these resources:
cd path/to/<app-name>
tower generate scaffold Post title:string content:string hasMany:comments
tower generate scaffold Comment title:string content:string belongsTo:post postID:string
Notice that the “postID” field is of type “String” and not “Integer” as you may be familiar with. Tower creates a rather long string, consisting of numbers and letters instead of the traditional incrementing Integer.
The Models, Controllers and Views are now created. If you open your app in a text editor you can take a look for yourself. Most of the good stuff is under the app
folder.
If you're new to MVC - the order in which things happen is:
- Browser asks the Controller for something
- Controller queries the database for a Model object(s)
- A Model instance is returned
- The Controller then puts the Model object(s) in the View
So far we have given our Post and Comment models relationships with each other. But for this to work we need to tell the Controller how to show Comments that belong to a particular Post.
In your app/controllers/server/postController.coffee
file add:
show: ->
App.Post.find @params.id, (error, @post) =>
if @post
@comments = {}
@post.get('comments').all (error, @comments) =>
@render "show"
Asynchronous is not a pleasant word for beginners. All it really means is that Node is a multitasker. If you ask it to pour a cup of coffee, answer the phone and fax that TPS report, it will do all 3 things at once (but do them really well).
So when you ask Node to do something, you have to provide a callback. A callback is piece of code that will be run after the first task is complete. The JavaScript convention is to put the callback function as the last paramater of the function call.
This can be confusing for newcomers... we’re used to putting things in to function paramaters, not giving it another place to go to.
This means that in the above example, when we ask Tower to fetch all Posts, we can’t ask it to then fetch comments attached to these posts, because Node will try to do at both at once and miss out a very important relationship.
Afraid of code? Face your fear head on with the Tower Console.
I find the best way to get a feel for a framework is by hacking in a console as it provides instant feedback. In your Tower directory enter:
tower console -c # the -c option lets you use CoffeeScript.
Creating a post is a 2 step process. First we use the build() function on our User class, passing in values which our object will accept. You may have noticed the curly brackets {}. JavaScript uses these heavily to structure data and you can think of these as ‘objects’. The save() on the end saves this to the database.
post = App.Post.build({name: "My Test Post", content: "..."})
post.save()
You will also see this record instantly popup in the browser, magic!
To list all records saved so far use:
posts = _.stringify(App.Post.all())
And to view the first record:
posts.objectAt(0)
In the tower directory (not in console mode), run:
tower select posts --select id,createdAt --where 'createdAt: $gte: _(1).days().ago()' --order createdAt- --limit 10 --page 2
See Also: https://github.com/viatropos/tower/issues/300#issuecomment-8787141
comment = App.Comment.build({postID: '5056b7a85296731623000001', name:'My Test Post', content: "..."})
comment.save()
...
allShops = App.Shop.all (error, shops) => shops
allShops.objectAt(0)
Tower uses a NoSQL called MongoDB. That means that instead of your data being stored in rows and columns of a table, each record is stored as a JSON object.
A common need is to reset the data in your database. Do this by opening the terminal and typing:
mongo
Then type show dbs
to list the databases.
Switch to your current database with use <database-name>
Then the magic command is:
db.dropDatabase();
Note: The Mongo console is JavaScript, not CoffeeScript, so all those ugly semicolons and things are required.
Use npm show [package-name] versions
to show all available versions on the NPM registry.
Run npm cache clean
when you’re having trouble installing newer versions of packages.
npm config delete NODE_ENV --global
…..not sure what this one does!