Thursday, 1 November 2012

Hacking on node.js and geddy

Geddy is a (rails like) simple, structured web framework for nodejs.

STEP 0 : install nodejs
METHOD 1 : using NVM
         $ curl https://raw.github.com/creationix/nvm/master/install.sh | sh
         $ source ~/.profile
         $ nvm install 0.10
         $ nvm use 0.10
         $ node -v
         
METHOD 2 : 
         $ wget http://nodejs.org/dist/node-v0.4.4.tar.gz 
         $ tar -zxf node-v0.4.4.tar.gz 
         $ cd node-v0.4.4.tar.gz 
         $ ./configure 
         $ sudo make install

STEP 1 : update npm
prayag@prayag:~$ sudo npm update -g
[sudo] password for prayag: 
npm http GET https://registry.npmjs.org/npm
npm http GET https://registry.npmjs.org/jake
npm http 304 https://registry.npmjs.org/jake
npm http GET https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/utilities
npm http 304 https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/lru-cache
npm http GET https://registry.npmjs.org/sigmund
npm http 304 https://registry.npmjs.org/utilities
npm http 304 https://registry.npmjs.org/lru-cache
npm http 304 https://registry.npmjs.org/sigmund
npm http 200 https://registry.npmjs.org/npm
npm http GET https://registry.npmjs.org/npm/-/npm-1.1.65.tgz
npm http 200 https://registry.npmjs.org/npm/-/npm-1.1.65.tgz
npm http GET https://registry.npmjs.org/npm/1.1.65
npm http 200 https://registry.npmjs.org/npm/1.1.65
npm http GET https://registry.npmjs.org/npm/-/npm-1.1.65.tgz
npm http 200 https://registry.npmjs.org/npm/-/npm-1.1.65.tgz
npm http GET https://registry.npmjs.org/node-uuid
npm http GET https://registry.npmjs.org/proto-list
npm http 200 https://registry.npmjs.org/node-uuid
npm http GET https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz
npm http 200 https://registry.npmjs.org/proto-list
npm http GET https://registry.npmjs.org/proto-list/-/proto-list-1.2.2.tgz
npm http 200 https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz
npm http 200 https://registry.npmjs.org/proto-list/-/proto-list-1.2.2.tgz
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
proto-list@1.2.2 /usr/local/lib/node_modules/npm/node_modules/proto-list

node-uuid@1.3.3 /usr/local/lib/node_modules/npm/node_modules/node-uuid



STEP 2 : install geddy and jake (JS build tool for nodejs)
prayag@prayag:~$ npm install -g geddy jake
npm http GET https://registry.npmjs.org/geddy
npm http 304 https://registry.npmjs.org/geddy
npm http GET https://registry.npmjs.org/utilities
npm http GET https://registry.npmjs.org/model
npm http GET https://registry.npmjs.org/jake
npm http GET https://registry.npmjs.org/barista
npm http 304 https://registry.npmjs.org/utilities
npm http 304 https://registry.npmjs.org/barista
npm http 304 https://registry.npmjs.org/jake
npm http 200 https://registry.npmjs.org/model
npm http GET https://registry.npmjs.org/model/-/model-0.0.18.tgz
npm http 200 https://registry.npmjs.org/model/-/model-0.0.18.tgz
npm http GET https://registry.npmjs.org/inflection
npm http GET https://registry.npmjs.org/minimatch
npm http 304 https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/lru-cache
npm http GET https://registry.npmjs.org/sigmund
npm http 200 https://registry.npmjs.org/inflection
npm http GET https://registry.npmjs.org/inflection/-/inflection-1.2.3.tgz
npm http 304 https://registry.npmjs.org/sigmund
npm http 304 https://registry.npmjs.org/lru-cache
npm http 200 https://registry.npmjs.org/inflection/-/inflection-1.2.3.tgz
/usr/local/bin/geddy -> /usr/local/lib/node_modules/geddy/bin/cli.js
geddy@0.5.7 /usr/local/lib/node_modules/geddy
├── model@0.0.18
├── utilities@0.0.15
├── jake@0.5.5 (minimatch@0.2.9)
└── barista@0.0.8 (inflection@1.2.3)


STEP 3 : creating a geddy app
prayag@prayag:~$ cd workspace.nodejs/
prayag@prayag:~/workspace.nodejs$ geddy app katahar
Created app katahar.

STEP 4 : structure of app
prayag@prayag:~/workspace.nodejs$ cd katahar/
prayag@prayag:~/workspace.nodejs/katahar$ ls -l
total 32
drwxr-xr-x 6 prayag prayag 4096 Oct 31 19:43 app
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 config
-rw-rw-r-- 1 prayag prayag  138 Oct 31 19:43 Jakefile
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 lib
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 log
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 node_modules
drwxr-xr-x 5 prayag prayag 4096 Oct 31 19:43 public
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 test

prayag@prayag:~/workspace.nodejs/katahar$ cd app/
prayag@prayag:~/workspace.nodejs/katahar/app$ ls -l
total 16
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 controllers
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 helpers
drwxr-xr-x 2 prayag prayag 4096 Oct 31 19:43 models
drwxr-xr-x 4 prayag prayag 4096 Oct 31 19:43 views


STEP 5 : install mongodb and mongodb-wrapper
for mongodb, 
download it from http://www.mongodb.org/downloads
or use Ubuntu package management tool, ie
5A) import the 10gen public GPG Key:

prayag@prayag:~/workspace.nodejs$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /tmp/tmp.6pdkCY14rL --trustdb-name /etc/apt/trustdb.gpg --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver keyserver.ubuntu.com --recv 7F0CEB10
gpg: requesting key 7F0CEB10 from hkp server keyserver.ubuntu.com
gpg: key 7F0CEB10: public key "Richard Kreuter <richard@10gen.com>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

5B) Then add 10gen to /etc/apt/sources.list 
prayag@prayag:~/workspace.nodejs$ sudo gedit /etc/apt/sources.list
...
.....


## This software is not part of Ubuntu, but is offered by third-party

## developers who want to ship their latest software.

deb http://extras.ubuntu.com/ubuntu precise main

deb-src http://extras.ubuntu.com/ubuntu precise main



#Add Only this line to the end of file

deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen



5C) reload repository
prayag@prayag:~/workspace.nodejs$ sudo apt-get update
[...]
Get:1 http://downloads-distro.mongodb.org dist Release.gpg [490 B]
[...]

Get:2 http://downloads-distro.mongodb.org dist Release [2,096 B]
[...]
Get:3 http://downloads-distro.mongodb.org dist/10gen i386 Packages [1,078 B] 
[...]

Ign http://downloads-distro.mongodb.org dist/10gen Translation-en_GB                                                                                                   
Ign http://downloads-distro.mongodb.org dist/10gen Translation-en  


5D) install mongo
prayag@prayag:~/workspace.nodejs$ sudo apt-get install mongodb-10gen

mongodb will be installed with mongodb conf file at /etc/mongodb.conf.

5E) after installation, check mongodb status
prayag@prayag:~/workspace.nodejs$ sudo service mongodb status
mongodb start/running, process 19625


for mongodb-wrapper
cd into your app and run this command:
prayag@prayag:~/workspace.nodejs/katahar/app$ sudo npm install mongodb-wrapper



STEP 6 : configure database
prayag@prayag:~/workspace.nodejs/katahar$ sudo vi config/development.js


var config = {
  detailedErrors: true
, debug: true
, hostname: null
, port: 4000
, model: {
    defaultAdapter: 'mongo'
        }
, db:{
        mongo:{
                dbname:"Katahar"
              }
     }
, sessions: {
    store: 'memory'
  , key: 'sid'
  , expiry: 14 * 24 * 60 * 60
  }
//, socketIo : true
};

module.exports = config;



STEP 7 :  make some changes in app/views/layout/application.html.ejs and app/views/main/index.html.ejs

prayag@prayag:~/workspace.nodejs/katahar$ sudo vi app/views/layouts/application.html.ejs

<title>Katahar Store</title>
...
......
<!-- add items to navigation -->
<div class="navbar navbar-fixed-top">
      <div class="navbar-inner">
        <div class="container">
          <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
            <span class="i-bar"><i class="icon-chevron-down icon-white"></i></span>
          </a>
          <%- linkTo('Katahar Store', '/', { class: 'brand' }) %>
          <div class="nav-collapse">
            <ul class="nav">
              <li class="active"><%- linkTo('Home', '/') %></li>
              <li><%- linkTo('Food Items', '/items') %></li>
            </ul>
          </div><!--/.nav-collapse -->
        </div>
      </div>
    </div>


prayag@prayag:~/workspace.nodejs/katahar$ sudo vi  app/views/main/index.html.ejs

<!-- Lets talk about geddy -->
<div class="hero-unit geddy-welcome-box">
  <h1>Katahar Store!</h1>
  <p>Welcome to Katahar ! </p>
</div>

Scaffolding creates full CRUD actions including views, and default configuration to use Mongodb Resource routes will be created for.
8.A)
prayag@prayag:~/workspace.nodejs/katahar$ geddy scaffold Item id:string name:string description:string active:boolean
[Added] app/models/item.js
Creating table for Item
[Added] test/item.js
[Added] app/controllers/items.js
[Added] Resource items route added to config/router.js
[Added] View templates

8.B) Check config/router.js for items mapping

prayag@prayag:~/workspace.nodejs/katahar$ sudo vi config/router.js 

var router = new geddy.RegExpRouter();


router.get('/').to('Main.index');


// Basic routes

// router.match('/moving/pictures/:id', 'GET').to('Moving.pictures');
//
// router.match('/farewells/:farewelltype/kings/:kingid', 'GET').to('Farewells.kings');
//
// Can also match specific HTTP methods only
// router.get('/xandadu').to('Xanadu.specialHandler');
// router.del('/xandadu/:id').to('Xanadu.killItWithFire');
//
// Resource-based routes
// router.resource('hemispheres');
//
// Nested Resource-based routes
// router.resource('hemispheres', function(){
//   this.resource('countries');
//   this.get('/print(.:format)').to('Hemispheres.print');
// });

router.resource('items');

exports.router = router;



8.C) check item model
prayag@prayag:~/workspace.nodejs/katahar$ ls -l app/models/
total 8
-rw-rw-r-- 1 prayag prayag 1206 Nov  2 20:57 item.js

The item.js model is as follows:


var Item = function () {

  this.defineProperties({

    name: {type: 'string', required: true},
    description: {type: 'string'},
    active: {type: 'boolean'},
  });
};

/*

// Can also define them on the prototype
Item.prototype.someOtherMethod = function () {
  // Do some other stuff
};

// Can also define static methods and properties

Item.someStaticMethod = function () {
  // Do some other stuff
};

// Can also define static methods and properties
Item.someStaticMethod = function () {
  // Do some other stuff
};
Item.someStaticProperty = 'YYZ';
*/

Item = geddy.model.register('Item', Item);


8.D)items directory inside app/views looks as follows:
prayag@prayag:~/workspace.nodejs/katahar$ ls -l app/views/items/
total 16
-rw-rw-r-- 1 prayag prayag 1346 Nov  2 20:57 add.html.ejs
-rw-rw-r-- 1 prayag prayag 1722 Nov  2 20:57 edit.html.ejs
-rw-rw-r-- 1 prayag prayag  447 Nov  2 20:57 index.html.ejs
-rw-rw-r-- 1 prayag prayag  419 Nov  2 20:57 show.html.ejs


STEP 9 : run server
prayag@prayag:~/workspace.nodejs/katahar/app$ geddy
[Wed, 31 Oct 2012 14:02:05 GMT] INFO Server starting with config: {
  "environment": "development",
  "workers": 1,
  "port": 4000,
  "debug": true,
  "rotateWorkers": false,
  "rotationWindow": 7200000,
  "rotationTimeout": 300000,
  "logDir": "/home/prayag/workspace.nodejs/katahar/log",
  "gracefulShutdownTimeout": 30000,
  "heartbeatInterval": 5000,
  "heartbeatWindow": 20000,
  "staticFilePath": "/home/prayag/workspace.nodejs/katahar/public",
  "sessions": {
    "store": "memory",
    "key": "sid",
    "expiry": 1209600
  },
  "cookieSessionKey": "sdata",
  "metrics": null,
  "i18n": {
    "defaultLocale": "en-us",
    "loadPaths": [
      "/home/prayag/workspace.nodejs/katahar/config/locales"
    ]
  },
  "spdy": null,
  "ssl": null,
  "hostname": null,
  "connectCompatibility": false,
  "detailedErrors": true,
  "model": {
    "defaultAdapter": "mongo"
  },
  "db": {
    "mongo": {
      "dbname": "Katahar"
    }
  }
}
[Fri, 02 Nov 2012 13:38:13 GMT] INFO Creating 1 worker process.
[Fri, 02 Nov 2012 13:38:14 GMT] INFO Server worker running in development on port 4000 with a PID of: 4346
[Fri, 02 Nov 2012 13:38:14 GMT] DEBUG LOGGING STARTED ============================================
[Fri, 02 Nov 2012 13:38:14 GMT] DEBUG ============================================================


STEP 10 : Goto browser, and hit http://localhost:4000

STEP 11 : add items and check mongodb
Add items using UI, and then connect to mongodb through interactive shell,

prayag@prayag:~/workspace.nodejs/katahar/app$ mongo Katahar
MongoDB shell version: 2.2.1
connecting to: Katahar
show collections;
items
system.indexes


Fire following command to query items collection

> db.items.find();

  "createdAt" : ISODate("2012-11-02T21:29:47.291Z"), 
  "updatedAt" : ISODate("2012-11-02T22:09:18.970Z"), 
  "name" : "Apple", 
  "description" : "Apple is a fruit.", 
  "active" : true, 
  "_id" : ObjectId("50943b4b158ce8804d000001"), 
  "id" : "A75E197D-7138-4673-9C85-933BC4D41407" 
}




References
1 - http://geddyjs.org/tutorial
2 - http://net.tutsplus.com/tutorials/javascript-ajax/persisting-your-todo-list-with-mongodb-and-geddy/
3 - http://nodeguide.com/beginner.html#installation

No comments:

Post a Comment