Wednesday, April 10, 2013

v0.3.15 - Node.js MVC: Express.js + Derby.js Hello World Tutorial

DerbyJS — Node.js MVC Framework

Express.js is a popular node frameworks which uses middleware concept to enhance functionality of applications. Derby is a new sophisticated Model View Controller (MVC) framework which is designed to be used with Express as it’s middleware. Derby also comes with the support ofRacer, data synchronization engine, and Handlebars-like template engine among many other features.

Derby.js Installation

Let’s set up a basic Derby application architecture without the use of scaffolding. Usually project generators are confusing when people just start to learn a new comprehensive framework. This is a bare minimum “Hello World” application tutorial that still illustrates Derby skeleton and demonstrates live-templates with websockets.
Of course we’ll need Node.js and NPM which can be obtained atnodejs.org. To install derby globally run:
$ npm install -g derby
To check the installation:
$ derby -V
My version as of April 2013 is 0.3.15. We should be good to go to creating our first app!

File Structure in a Derby.js App

This is the project folder structure:
project/
  -package.json
  -index.js
  -derby-app.js
  views/
    derby-app.html
  styles/
    derby-app.less

Dependencies for The Derby.js Project

Let’s include dependencies and other basic information in package.jsonfile:
 {
  "name": "DerbyTutorial",
  "description": "",
  "version": "0.0.0",
  "main": "./server.js",
  "dependencies": {
    "derby": "*",
    "express": "3.x"
  },
  "private": true
}
Now we can run npm install which will download our dependencies intonode_modules folder.

Views in Derby.js

Views must be in views folder and they must be either in index.htmlunder a folder which has the same name as your derby app JavaScript file, i.e., views/derby-app/index.html, or be inside of a file which has the same name as your derby app JS file, i.e., derby-app.html.
In this example “Hello World” app we’ll use <Body:> template and{message} variable. Derby uses mustach-handlebars-like syntax for reactive binding. index.html looks like this:
<Body:>
  <input value="{message}"><h1>{message}</h1>
Same thing with Stylus/LESS files, in our example index.css has just one line:
h1 {
  color: blue;
}
To find out more about those wonderful CSS preprocessors check out documentation at Stylus and LESS.

Building The Main Derby.js Server

index.js is our main server file, and we begin it with an inclusion of dependencies with require() function:
var http = require('http'),
  express = require('express'),
  derby = require('derby'),
  derbyApp = require('./derby-app');
Last line is our derby application file derby-app.js.
Now we’re creating Express.js application (v3.x has significant differences between 2.x) and an HTTP server:
var expressApp = new express(),
  server = http.createServer(expressApp);
Derby uses Racer data synchronization library which we create like this:
var store = derby.createStore({
  listen: server
});
To fetch some data from back-end to the front-end we instantiate model object:
var model = store.createModel();
Most importantly we need to pass model and routes as middlewares to Express.js app. We need to expose public folder for socket.io to work properly.
expressApp.
  use(store.modelMiddleware()).
  use(express.static(__dirname + '/public')).
  use(derbyApp.router()).
  use(expressApp.router);
Now we can start the server on port 3001 (or any other):
server.listen(3001, function(){
  model.set('message', 'Hello World!');
});
Full code of index.js file:
var http = require('http'),
  express = require('express'),
  derby = require('derby'),
  derbyApp = require('./derby-app');

var expressApp = new express(),
  server = http.createServer(expressApp);

var store = derby.createStore({
  listen: server
});

var model = store.createModel();

expressApp.
  use(store.modelMiddleware()).
  use(express.static(__dirname + '/public')).
  use(derbyApp.router()).
  use(expressApp.router);

server.listen(3001, function(){
  model.set('message', 'Hello World!');
});

Derby.js Application

Finally, Derby app file which contains code for both a front-end and a back-end. Front-end only code is inside of app.ready() callback. To start, let’s require and create an app. Derby uses unusual construction (not the same familiar good old module.exports = app):
var derby = require('derby'),
  app = derby.createApp(module);
To make socket.io magic work we need to subscribe model attribute to its visual representation, in other words bind data and view. We can do it in the root route, and this is how we define it (patter is /, a.k.a. root):
app.get('/', function(page, model, params) {
  model.subscribe('message', function() {
    page.render();  
  })  
});
Full code of derby-app.js file:
var derby = require('derby'),
  app = derby.createApp(module);

app.get('/', function(page, model, params) {
  model.subscribe('message', function() {
    page.render();  
  })  
});  

Launching Hello World App

Now everything should be ready to boot our server. Execute node . ornode index.js and open a browser at http://localhost:3001. You should be able to see something like this: http://cl.ly/image/3J1O0I3n1T46.
Derby + Express.js Hello World App

Passing Values to Back-End in Derby.js

Of course static data is not much, so we can slightly modify our app to make back-end and front-end pieces talks with each other.
In the server file index.js add store.afterDb to listen to set events onmessage attribute:
server.listen(3001, function(){
  model.set('message', 'Hello World!');
  store.afterDb('set','message', function(txn, doc, prevDoc, done){
    console.log(txn)
    done();
  }) 
});
Full code of index.js after modifications:
var http = require('http'),
  express = require('express'),
  derby = require('derby'),
  derbyApp = require('./derby-app');

var expressApp = new express(),
  server = http.createServer(expressApp);

var store = derby.createStore({
  listen: server
});

var model = store.createModel();

expressApp.
  use(store.modelMiddleware()).
  use(express.static(__dirname + '/public')).
  use(derbyApp.router()).
  use(expressApp.router);

server.listen(3001, function(){
  model.set('message', 'Hello World!');
  store.afterDb('set','message', function(txn, doc, prevDoc, done){
    console.log(txn)
    done();
  })   
});
In Derby application file derby-app.js add model.on() to app.ready():
  app.ready(function(model){
     model.on('set', 'message',function(path, object){
     console.log('message has been changed: '+ object);
   })
  });
Full derby-app.js file after modifications:
var derby = require('derby'),
  app = derby.createApp(module);

app.get('/', function(page, model, params) {
  model.subscribe('message', function() {
    page.render();
  })
});

app.ready(function(model) {
  model.on('set', 'message', function(path, object) {
    console.log('message has been changed: ' + object);
  })
});
Now we’ll see logs both in the terminal window and in the browser Developer Tools console. The end result should look like this in the browser: http://cl.ly/image/0p3z1G3M1E2c, and like this in the terminal:http://cl.ly/image/322I1u002n38.
Hello World App: Browser Console Logs
Hello World App: Terminal Console Logs
For more magic in the persistence area, check out Racer’s db property. With it you can set up an automatic synch between views and database!
Let me know if you’re interested in any specific topic for future blog post and don’t forget to checkout my JavaScript books:
The full code of all the files in this Express.js + Derby Hello World app is available as a gist at https://gist.github.com/azat-co/5530311

Wednesday, October 17, 2012

Derby.js – The Ready() Function, and Adding Client-Side Scripts to your App

I’ve found a neat feature of derby dealing with the ready() function.
I’ve been creating a derby app, and in my application I need to load up a client-side calendar. With a standard HTML web page this is straightforward thing to do. On the page you wanted the calendar, you would include the client js for the calendar, some code to load it, and that would be that.
Derby introduced some complexity to this relatively simple task.
On my first attempt, I put my scripts in the section of the page that I needed the calendar on. I added a script to load the calendar as well. When I went to the url of the page, it loaded immediately. Success! (I thought).
Then I clicked a link away from my calendar, and then clicked back. No calendar.
What happened? When I loaded the link originally, the page was rendered from the server. The second time, the page was rendered client side. Something wasn’t working with loading the calendar on the client-side render.
You need a place to put your code that guarantees that it will load on the client-side. Theapp.ready() function is designed to handle this scenario.
What is the purpose of the app.ready() function? From the derby documentation:
Code that responds to user events and model events should be placed within the app.ready() callback. This provides the model object for the client and makes sure that the code is only executed on the client.
This function is called as soon as the Derby app is loaded on the client. Note that any code within this callback is only executed on the client and not on the server.
I’ve bolded the part I think is particularly important. This code is run as soon as the client is loaded. Which means if you have more than a single-page app, using app.ready() to load a feature might not work out.
So what to do? An undocumented feature of Derby – app.on().
What does it do? It allows you to load code AFTER a specific page has loaded. Which is exactly what I’m looking for.
So here’s what I ended up writing in my app.ready():
1
2
3
4
app.on('render:calendar', function(ctx) {
  logger.log("rendering calendar client-side...");
  new Timeline("timeline", new Date());
});
In this example this code will run after rendering the calendar view. On the Calendar page, there is a script block which loads the Timeline function.
After writing this code, I tried my page again. Still no luck. I wasn’t getting the calendar to load on both the client and server load.
On a lark, I moved the block containing my Timeline javascript to my index view, and tried again. Success.
Which makes sense. If you are rendering pages via the client side load, additional resources aren’t going to be loaded. So by putting my script into the index view, it’s unfortunately loaded for all my pages, but at least it’s available for both the client and server side rendering of my cool control.

Thursday, September 6, 2012

Setting up MongoDB to work with Derby.js

This post is going to cover installing and configuring MongoDB to use with Derby.
If you’re reading this post looking to add model persistence to your Derby application but don’t know much about MongoDB, understanding MongoDB will help you understand Derby and the model system it uses.

What’s MongoDB?

From their website:
MongoDB (from “humongous”) is a scalable, high-performance, open source NoSQL database.
If you’ve never used MongoDB before, you should immediately go here. This is the easiest, fastest way to learn the basics of what mongo is and how it works. And it only takes about fifteen minutes. It’s even interactive to keep you from getting bored. Go give it a play.

Derby and MongoDB

Now that you have an idea about how MongoDB works, many of the conventions Derby uses for models should make sense. If you scan through the Derby Query Readme now, hopefully is makes a bit more sense (like where the term “gte” came from).

Installing MongoDB

If you still need to install MongoDB go here for downloads and installation directions.

Configuring Derby to use MongoDB

Now that you know about MongoDB, let’s get MongoDB set up to work with Derby. This is straightforward and takes about two minutes.
To add MongoDB to your Derby application, you’ll need to include the racer-db-mongopackage in your project.
Update your package.json file to look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "name": "potluck",
  "description": "",
  "version": "0.0.1",
  "main": "./server.js",
  "dependencies": {
    "derby": "*",
    "derby-ui-boot": "*",
    "express": "3.0.0beta4",
    "gzippo": ">=0.1.7",
    "racer-db-mongo": "*" //this is the line. Glory in its beauty.
  },
  "private": true
}
Then, at the command prompt, update your project (and download the recently addedracer-db-mongo dependency) using the following command:
 npm update 
You’ll have to update your server configuration (by default in /lib/server/index.js) to use the new dependency. This requires TWO new lines of code
1
2
3
4
5
6
derby.use(require('racer-db-mongo')); // This line is new
 
app.createStore({
  listen:  server
, db:      {type: 'Mongo', uri: 'mongodb://localhost/database'} /* This line is new */
});
That’s all the changes you need to make to add MongoDB to your project. So why I’d bother with a blog post?

What About Troubleshooting?

Now, if you go and start your Derby application, you might see the following error:
Error: failed to connect to [localhost:27017]
Which means:
  1. You’ve installed the racer-db-mongo dependency correctly!
  2. You now need to:
    • Install MongoDB
    • Turn on MongoDB
    • OR Fix MongoDB
If you’ve forgotten to install Mongo, if you look around, you’ll probably find a link somewhere which will help you out.

Starting/Stopping/Statusing MongoDB

If you’ve installed Mongo, you have to start the service before Derby can use it. On Ubuntu, you start Mongo using the following command:
 sudo start mongodb 
Remember to stop Mongo later with:
 sudo stop mongodb 
If you’ve started Mongo, then loaded your Derby application, and you’re still getting an error, it’s possible that Mongo did not start correctly. Typing:
 sudo status mongodb 
will let you know if Mongo is running or not. If you’ve run the Mongo Start command, yet the status command is telling you that Mongo is stopped, the most likely cause is Mongo did not shut down gracefully last time it was run. You’ll have to go and repair your installation (luckily, this is pretty easy).

Repairing MongoDB

To repair your installation, run the following commands:
$ sudo rm /var/lib/mongodb/mongod.lock
$ sudo -u mongodb mongod -f /etc/mongodb.conf --repair 
The code above was taken from this great article
At this point, you should have a working copy on MongoDB along with a working integration with Derby. Congrats!

MongoDB is working great – now Derby hates me

If your application loads, but you’re getting a strange error whenever you add to a collection that looks something like this:
Error: No persistence handler for 
push(FIRST_WORD.SECOND_WORD, [object Object], 18) 
It means that you are pushing to the wrong portion on an model path. You can only use push to arrays, and arrays are not objects, and you can only use objects for the first and second words of your model path. In the case shown above, a push is attempting to be made to
 FIRST_WORD.SECOND_WORD 
which equates to
 FIRST_WORD.SECOND_WORD.push(object) 
which means SECOND_WORD is an array (which isn’t allowed).
If this last bit of explanation might have well been in Latin, check out this post. It’ll explain a little bit about how to declare models and what Derby is expecting you to do.
Unfortunately, you CAN use the second word of a model path as an array without persistence support. So this kind of bug will only surface once you’ve got MongoDB integrated with Derby.