Blog rolling with CouchDB, Express and Node.js

Over the last little while, I’ve been doing a lot of playing with Node.js, mostly to run data collection scripts. Last week, I started following Ciaran Jessup’s tutorial on getting started with node.js, Express and mongoDB. Express acts as a framework to node.js, allowing you to work in a familiar mvc format in a not so familar server side language. I hit a few problems along the way in the tutorial, so I thought I’ve list a few of my findings here. I also wanted to make use of my preferred flavour of nosql – couchdb with express, which proved extremely easy to port the mongo model over to it. I hope someone out there finds this useful as I’ve yet to find a vast community using couchdb/express.

First things first, you’ll want to install Node and npm (the node package manager) in order to be able to easily install node packages. You’ll also probably find it handy to have the original tutorial open alongside this one. I’ve been using the latest versions of node (0.3.7) and npm (0.2.17) at the time of writing.

Once that’s done, grab copies of the packages that we’ll be using:

npm install express
npm install jade
npm install sass

If you want to use couchdb, then make sure you have it installed – grab it over here and then install the package for talking to node.

npm install cradle

The first hurdle I found was that the way in which that express is called has changed a little.

Then by saving to a file called app.js and calling using:

node app.js

Once that’s done. You can then visit 127.0.0.1:3000 in your browser to see a rivetting message!

After creating folder beneath our original app.js in which to put views, you can use the original article provider file and the updated app.js below in order to have an app with a few articles shown.

Now when you re-run, you’ll see 3 separate articles. Oooh fancy!

Next I hit my first hurdle. Express no longer uses the HAML HTML template language and instead uses JADE by default. This requires converting the HAML templates across to their equivalent JADE counterparts. Basically, this is as simple as dropping the ‘%’ from the beginning of each line (I also replaced braces with brackets in later templates).

The app.js now becomes:

You’ll notice that here we enable the CSS compiler sass and HTML compiler jade. If you download the original sass CSS template into your views folder, you can now restart the app and inspect the fruits of your labour. The CSS shouldn’t actually sit in the views folder, according to the creator of Express, and should instead should be compiled with the sass package itself. I’ve yet to discover the correct way of doing this. To request a stylesheet in the view, we need to do the following:

If you reload now and visit 127.0.0.1:3000 you should see your posts with a little more style.

Creating a form for new posts looks like this:

And the new app.js routes are as follows:

In order to add persistence using mongodb, nothing changes in the original model file, so go ahead and use that. You’ll need to have installed the package ‘mongodb’ if you’d like to try out using it though and update your instantiation of the articleprovider class by supplying a port number to which mongo is installed.

Adding CouchDB Persistence

Here, I took my own angle on the tutorial and decided to give attempting to make my own persistence model using couchdb a go. It proved to be extremely easy, given the JSON representation and HTTP/GET method of access already built in to it.

I added the following view and route to my app.js too, to allow support for clicking upon articles.


And in order to support it, the main view now becomes as follows:

Anyway, so far I’ve not yet added comment support, but given the headway I made here, I’d imagine it would be extremely easy to integrate into my couchdb article model. I’ll update here if I ever get round to adding it!

17 comments so far

  1. Luc

    Hello,
    I have a problem with the first server of this tutorial, when I run the node app.js, I get the following error:

    node app.js

    node.js:134
    throw e; // process.nextTick error, or ‘error’ event on first tick
    ^
    TypeError: Object # has no method ‘bodyDecoder’
    at HTTPServer. (/Users/luc/Projects/testnode/app.js:7:19)
    at HTTPServer.configure (/usr/local/lib/node/.npm/express/2.2.1/package/lib/http.js:445:8)
    at Object. (/Users/luc/Projects/testnode/app.js:5:5)
    at Module._compile (module.js:404:26)
    at Object..js (module.js:410:10)
    at Module.load (module.js:336:31)
    at Function._load (module.js:297:12)
    at Array. (module.js:423:10)
    at EventEmitter._tickCallback (node.js:126:26)

    Any idea ?
    Thanks for your tutorial, I really want to give node.js a try.
    Luc

  2. Luc

    Hmmm… ok, seems it’s ok when I comment the line:

    app.use(express.bodyDecoder());

    I’m too new to node.js to find an explanation to this :)

    Regards,
    Luc

  3. Ian

    Hi Luc,

    Not entirely sure, but I’d check whether you’re running the same version of node as me (0.3.7) for a start, I had to make some updates based on different versions of the modules I was using compared to the original article.

  4. Luc

    Hi Ian,
    You’r right, I use the 0.4.4.
    Thanks a lot for your great article !!! Node and it’s ecosystem is really cool stuff.
    Luc

  5. One thing to note is that the view ‘articles/all’ has to be previously created, either via the couchdb web interface, or programatically What I did, though I’m not sure it’s the right way, is put the following code in articleprovider-couchdb.js, right after connecting to the database:

    this.db.save('_design/articles', {
    all: {
    map: function (doc) {
    if (doc.title) emit(doc.title, doc);
    }
    }
    });

    Is that really stupid?

  6. Ian

    Jonathan, good point. I should really highlight that in my tutorial.

    I’m not sure what the official stance on whether it is better to implement your views in your code or not. My guess it’s always better to have them in couch itself. Mine were created through Futon and saved under /_design/articles/view/all.


    function(doc) {
    emit(doc._id, doc);
    }

    If you’re adding to articleprovider-couchdb.js my guess is that that view will be created each and every time you fire up your express app, which isn’t really necessary.

  7. Yes, creating them in couch does sound better. I agree with your point that articleprovider-couchdb.js will try and create the view everytime it is called…

    Thanks for the great post anyway!

  8. angel

    I don’t know why…if I’m copy your code when I run it, inside my post (/blog/new) form my request params are empty req.param(‘title’) or name are complety empty, I tried debbuging this and actually they aren’t receive the data from my view and I get a “undefined…when I work with sinatra I need send a new object to my view where it is fill (@article is initializate in get(/article/new)) and when it return I save it…is it different in express?…thanks a lot and I really appreciate your contribution (it’s the best of the few tutoriales about express where don’t make something really basic and I love couchdb)

  9. Köntzä

    About the process.nextTick error: it seems bodyDecoder is now called bodyParser. If you change bodyDecoder to bodyParser in the code above, the nextTick error will go away.

  10. Michael Rand

    Great post … used it to get the CRU piece of a CRUD blog working.

    How would you implement a post Delete function? The trick seems to be how to get the revision # as well as the ID to this.db.remove, since realistically only the ID is sitting in the URL.

  11. Michael Rand

    Also, I believe the best way to push views, etc. into couch is to use couchapp (either the Python or Node flavor). I used it to push the all view into couch, and it works great.

    Just organize your project like this:

    project
    _project_express
    project_couchapp

    and put project under source control. Works like a charm.

  12. Replaced bodyDecoder() with bodyParser() and that will get the code working people. Excellent tutorial by the way, really helped me out learning Node.js and CouchDB – so thank you.

  13. Ian

    Thanks very much Dwayne. There’s been a few changes in node since I wrote this, bodyParser() being one of them.

  14. Pingback: Node.js experiment part 1: Defining my experiment « BaconFriedRice.com

  15. jeangui

    Hi,

    Thanks a lot for your tutorial ! It is a very good starting point to learn node.js and play with couchdb.

    Everything is going fine from my side but there is still a problem with the style sass compilation. First the link to the style.css.sass file is broken so I did create one from scratch :

    body
    font-family "Helvetica Neue", "Lucida Grande", "Arial"
    font-size 13px
    text-align center
    text-stroke 1px rgba(255, 255, 255, 0.1)
    color #555
    h1, h2
    margin 0
    font-size 22px
    color #343434
    h1
    text-shadow 1px 2px 2px #ddd
    font-size 60px
    #articles
    text-align left
    margin-left auto
    margin-right auto
    width 320px
    .article
    margin 20px
    .created_at
    display none
    .title
    font-weight bold
    text-decoration underline
    background-color #eee
    .body
    background-color #ffa

    I put it in the views/style.css.sass file…

    But my web page are never styled. I should miss something.

    I am working with cloud9. I did install sass and put


    var sass = require('sass');

    on top of the app.js file.

    Thanks in advance for your help.

    Best regards.

    Jeangui

  16. Ian

    Jeangui – You don’t need to explicitly require sass, although you’ll need to install it with npm. It’s pulled into express in the line app.use(express.compiler({ src: __dirname + '/views', enable: ['sass'] }));.

  17. jeangui

    Hi Ian,

    Thanks for your help. I did install sass (npm install sass and npm install sass -g) but it still doesnt work.
    How shoud I debug this ?
    Maybe a problem with Cloud9 ….

    Regards
    jg

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>