Node.JS and Heroku

I am following Node:Up and Running to learn about Node.JS and extending what I have gleaned from this book, and learned on the excellent Javascript courses at O’Reilly School of Technology, so that I can deploy the book example apps on a Heroku dyno. I like the way the book is written, but there are some really frustrating gaps — thus far. At least for a node.js n00b like me.

If you got stuck like me, here are some fixes. Most of these stem from a) typos and b) I assume, earlier versions of EJS and Express.

Chapter 2 — Example 2–1. A test for the POST API

The twitter_test.js file fails. This might be by design — but if you want to correct the test case then you need to fix the assert.strictEqual to equal res.send. The complete file then becomes:

var http = require('http'), assert = require('assert');
var opts = {
host: 'localhost',
port: 8000,
path: '/send',
method: 'POST',
headers: {'content-type':'application/x-www-form-urlencoded'}
}
var req = http.request(opts, function(res) {
res.setEncoding('utf8');
var data = "";
res.on('data', function(d) {
data += d;
})
res.on('end', function() {
assert.strictEqual(data, '{status:"ok", message:"Tweet received"}');
})
})
req.write('tweet=test');
req.end();
Chapter 2 - Examples 2-17 through 2-22.  Getting the Chirpie site to work.
First off, you need to install EJS.  Do so from where your project is - so in my case, run it in the 'my app folder' - see below.
MyApp
├── app.js
├── public
└── views
└── partials
Run:
npm install ejs
In the node_modules folder you will see a folder for ejs.
What the book does not state is that the example code needs to be saved in files with a .ejs extension.  So index.ejs should exist in the views folder and chirp.ejs in the partials.  In addition, the body tag is no longer support so you need to break the layout of the page into the 'top' and the bottom'.
The folder structure, with files, now looks like this:
MyApp
├── app.js
├── public
├────── style.css
└── views
├── index.ejs
├── layoutBottom.ejs
├── layoutTop.ejs
└── partials
├── chirp.ejs
└── stylesheet.ejs
The content of the files is as follows:

app.js

var express = require('express');
var app = express();
app.listen(8000);
// Required to load the css stylesheet file defined in locals
app.use(express.static(__dirname + '/public'));
// New for Express 3.0
app.set("view engine", "ejs");
var tweets = [];
app.get('/', function(req, res) {
var title = 'Chirpie',
header = 'Welcome to Chirpie';
res.render('index', {
locals: {
'title': title,
'header': header,
'tweets': tweets,
stylesheets: ['style.css']
}
})
})
// bodyParser is 'middleware'
app.post('/send', express.bodyParser(),
function(req, res) {
if (req.body && req.body.tweet) {
tweets.push(req.body.tweet)
if (acceptsHtml(req.headers['accept'])) {
res.redirect('/', 302);
}
else {
res.send('{status:"ok", message:"Tweet received"}');
}
}
else {
// no tweet?
res.send('{status:"nok", message:"No tweet received"}');
}
})
app.get('/tweets', function(req,res) {
res.send(tweets);
})
// A small function to check for text/html in an accept header
function acceptsHtml(header) {
var accepts = header.split(',');
for (i=0; i < accepts.length; i++) {
if (accepts[i] == 'text/html') {
return true;
}
}
return false;
}
index.ejs
<% include layoutTop %>
<form action="/send" method="POST">
<input type="text" length="140" name="tweet">
<input type="submit" value="Tweet">
</form>
<% include partials/chirp %>
<% include layoutBottom %>

layoutTop.ejs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<% include partials/stylesheet %>
<title><%= title %></title>
</head>
<body>
<h1><%= header %></h1>

layoutBottom.ejs

</body>
</html>

chirp.ejs

<p><%= tweets %></p>

stylesheet.ejs

<link rel="stylesheet" href="<%- stylesheets %>">
Now when you run you should see the the Chirpe page with an input box.  Enter some text and hit 'tweet'.  You should see each tweet (aka 'chirp') appear below as a comma-delimited string.