Sunday, June 15, 2014

Part 1: Ember.js + Sails.js + PostgreSQL - An end-to-end technology-chain that enables rapid web application development in a RESTful fashion

Welcome document

Goal

Intention behind chaining technologies like Ember.js + Sails.js + PostgreSQL is to foster the below best practices in our end-to-end web application development (i.e. both client-side & server-side development).

Best Practices

Ember.js goodies [Client-side]
  • Single-Page Application (SPA) on the client-side for improved user-experience
  • MVC pattern that structure’s + manage’s interaction between the client-side software artifacts
  • Convention-Over-Configuration to achieve productivity & understandability during development/maintenance phases
Sails.js goodies [Server-side]
  • RESTful architectural style for piping CRUD operation between client-side calls & server-side persisted datasets
  • Convention-Over-Configuration to achieve productivity & understandability during development/maintenance phases
PostgreSQL goodies [Server-side]
  • ORDBMS, so as to harness its technological maturity & operational performance

By focusing on the above goodies, our goal in this blog-post is to primarily showcase technical details on how to chain such technologies together and at the same time introduce you to the rapid web application development that are highly maintainable.

Table of contents

Prerequisites

NOTE: Pre-installation of the following software is a must

  • Node.js & its NPM package manager
    • Bower npm package installed globally [sudo npm install -g bower]
    • Mimosa npm package installed globally [sudo npm install -g mimosa]
    • Sails.js npm package installed globally [sudo npm install -g sails]
  • PostgreSQL object-relational DBMS
  • Web-bowser i.e. latest Firefox or Google Chrome

Ember.js

Bootstrapping

My preferred way to bootstrap an Ember.js project is by using the ‘ember-peepcode’ seed. I primarily use this ‘ember-peepcode’ seed to bootstrap ember SPA app, because it takes into account the Emer.js framework’s best practices & at the same time it offers all my favourite HTML5 tooling:

  • CoffeeScript as the primary application development language
  • Mimosa as the build tool
  • Jade html template including emblem & hbs
  • Stylesheets written in stylus/less/sass/css
  • Locks on to Ember-Model rather then Ember-Data
  • Testing environment
  • Bower as the dependency manager

Now, let’s fire-up the above mentioned seed:

$ mkdir my-webapp
$ cd my-webapp
$ mimosa skel:new ember-peepcode
$ npm install
$ bower install

NOTE: When you run the ‘bower install’ command, if you get asked the below question, then your answer should be ‘!2’:

Unable to find a suitable version for ember, please choose one:
1) ember#~1.0 which resolved to 1.0.1 and is required by ember-model#0.0.11
2) ember#1.5.0 which resolved to 1.5.0 and is required by ember-mimosa-peepcode

Prefix the choice with ! to persist it to bower.json

[?] Answer: !2

Now, run the mimosa server with this command:

$ mimosa watch -s

Now, test the running sample SPA app by visit the following url in your favourite web-browser:

http://localhost:3000

Additional JS libraries

Now, let’s add the following JS libraries as dependencies to our SPA app:

  • Twitter bootstrap
  • Sails.js data adapter

Run the below two commands, so that the Bower can fetch dependencies & auto-magically install them for us:

$ bower install bootstrap --save
$ bower install ember-data-sails-adapter#1.0.1 --save

NOTE: When you run the ‘bower install ember-data-sails-adapter#1.0.1 –save’ command, if you get asked the below question, then your answer should be ‘!3’:

Unable to find a suitable version for ember, please choose one:
1) ember#~1.0.0 which resolved to 1.0.1 and is required by ember-data-sails-adapter#1.0.1
2) ember#~1.0 which resolved to 1.0.1 and is required by ember-model#0.0.11
3) ember#1.5.0 which resolved to 1.5.0 and is required by ember-mimosa-peepcode
4) ember#>= 1.0.0 which resolved to 1.5.0 and is required by ember-data#1.0.0-beta.8

Prefix the choice with ! to persist it to bower.json

[?] Answer: !3

Now, let’s include the above installed JS libraries in our SPA app. This is done by referencing the below listed files in ‘/assest/index.html.jade’:

link(rel='stylesheet', href='stylesheets/vendor/bower-assets//bootstrap/bootstrap.css')
script(src='javascripts/vendor/bower-assets/bootstrap/bootstrap.js')
script(src='javascripts/vendor/bower-assets/ember-data/ember-data.js')
script(src='javascripts/vendor/bower-assets/ember-data-sails-adapter/ember-data-sails-adapter.js')

Ember Inspector

Within the comfort of your web-browser, the Ember Inspector enables us to debug Ember specific entities, such as View Tree, Routes, Data, Promises, Render Performances, among others. For more information regarding Ember Inspector visit it’s Github repository.

You may install this Ember Inspector, which is available as a Add-on/Extension for your specific web-browser:

  • Firefox’s Ember Inspector add-on can be found here
  • Chrome’s Ember Inspector extension can be found here

Sails.js

Bootstrapping

Now, bootstrap a Sails.js project:

$ sails new colours-restful-api
$ cd colours-restful-api
$ sails lift --verbose

Note: The running sails server can be accessed on the following URL:
http://localhost:1337

PostgreSQL: Create a new database

Create a new PostgreSQL database for the purpose of this project. Name this database as:

test_db

Adding Domain Model+Controller

Now, let’s add a model + controller called ‘colours’. This will provide a RESTful interface for a colours entity:

$ sails generate colours

Now, enable CORS on all routes in the file ‘/config/cors.js’ as follows:

Note: This will enable cross-site calls

allRoutes: true

Now, install the PostgreSQL sails adapter. This adapter is an npm package, which is directly installed into your current project:

$ npm install sails-postgresql

Now, add the below postgreSQL configuration in the file ‘/config/adapters.js’:

'default': 'postgresql',

postgresql: {
    module: 'sails-postgresql',
    database: 'test_db',
    host: 'localhost',
    user: 'postgres',
    password: 'xxxx',
    port: 5432,
    pool: false,
    ssl: false
  }

Now, add the following two properties to the above created colours model, which is located in ‘/api/models/Colours.js’:

attributes: {
    name: 'string',
    symbol: 'string'
}

Now, kill the running sails server & restart it by firing-up the sails server with the below command:

$ sails lift --verbose

Note: To directly view the colours model’s JSON dataset, visit this URL:
http://localhost:1337/colours

Adoc testing CRUD-actions

Now, you are ready to conduct the below CRUD-action tests, within the comfort of your web-browser:

Note: This kind of testing implicitly tests the generated blueprint-shortcuts-routes

Find all colours:

 http://localhost:1337/colours

Create + Update colours:

 http://localhost:1337/colours/create?name=Red

 http://localhost:1337/colours/update?id=1&symbol=STOP

 http://localhost:1337/colours/create?name=Yellow

 http://localhost:1337/colours/update?id=2&symbol=GET SET

 http://localhost:1337/colours/create?name=Green

 http://localhost:1337/colours/update?id=3&symbol=Go

 http://localhost:1337/colours/create?name=Orange

 http://localhost:1337/colours/update?id=4&symbol=GET SET

 http://localhost:1337/colours/create?name=orange

Delete a colour:

 http://localhost:1337/colours/destroy?id=5

Conditional find:

 http://localhost:1337/colours?where={%22symbol%22:%22GET%20SET%22}&sort=name%20desc&limit=1

Source Code

You can view both the projects source code in its entirety, here’s the bitbucket repository:

Conclusion

What we have seen so far, is how to independently bootstrap client-side & server-side projects. Also, we conducted some basic adhoc testing on these projects. Therefore, what we have is:

  1. A SPA app built using Ember.js framework.

  2. A RESTful API built-up with help of Sails.js framework, which incorporate’s PostgreSQL as the ORDBMS.

This has give us the foundation & a jump start, to built required feature-set from now on. Feature-set such as, engaging user-experience on the client-side and comprehensive CRUD services in a data-centric/distributed fashion on the server-side. All these are achieved under the umbrella of good-practices & ease-of-maintenance. Thus, helping the app development to face upto ever changing requirements of the real-world.

Nonetheless, at present our client-side implementation doesn’t talk or consume services provided by server-side any how! This implementation is what’s expected next…

What’s next?

We will continue on the present foundation in the next blog-post and demonstrate the SPA app (i.e. client-side) feature-implementation, which invokes CRUD operations on the RESTful API (i.e. server-side).

Wednesday, May 28, 2014

Fundamental Concepts Within Ember.js

Ember.js, a client-side JavaScript web application framework. Ember.js (we simple call it Ember) helps in the development of Single-Page Applications (SPA) in a Reactive fashion.

Before moving on further, lets pose the below question:

Why develop a web app as supposed to a native GUI app?
Web application, technically means => The ability to bookmark and share URLs in as stateless fashion i.e. a superior shareability and collaboration as supposed to a native GUI app. Hence, the justification to develop web applications.

Ember as a SPA framework, its strengths are in combining tools and concepts of native GUI frameworks with support for URL. Therefore, making URL as a first-class citizen rather than an after thought.

To be an Ember literate, one has to deeply understand its native vocabulary-set/concepts, which can be abbreviated as TRC-MRC-VH and stands for:

T - Templates
R - Router
C - Components

M - Models
R - Route
C - Controllers

V - Views
H - Helpers




Below is my interpretation of the above concepts & their relationships to each other, as of Ember version 1.5.1.


Templates

Templates describe the apps user interface.

Features:
 a. Each template is backed by a model and automatically updates itself if the model changes.
 b. Templates are composed of one or more of the following: HTML, Expressions, Outlets, & Components. Where:
  i. Expressions: Refers to data-binding expressions, for e.g. {{firstName}}. Expressions once declared in the templates, it gets data-bound to respective model's/controller's properties.
  ii. Outlets: Refers to placeholders, into which templates are injected. Here, router is responsible for injecting templates into outlets.
  iii. Components: Refers to custom HTML elements, for e.g. {{#blog-post title=title}}. Which could to used for:
    1. Cleaning-up repetitive templates
    2. Creating reusable controls
 c. A template can optionally have a controller in addition to a model and can retrieve properties from both.
 d. Handlebars is used as the primary templating engine.
 e. On-demand pre-compilation of templates are possible. This allows organisation of the templates as separate .hbs or .handlebars files. Or directly declare following script tag => type="text/x-handlebars" in your HTML.

Example: JS Bin example of the above points (a, b.i, b.ii, c, d, e)


Router

A Router translates an URL into a series of nested templates. Which means, router is responsible for injecting templates into above mentioned outlets.


Components

Component is a custom HTML tag, which enables you to create reusable controls to the above mentioned templates.
  
Implementation aspects:
 a. Appearance is describe using Handlebars templates
 b. Behaviour is implemented using JavaScript

Example: Section on Showing confirmation modal-dialog in the tutorial Ember.js + Sails.js + PostgreSQL is an use case of components.


Models

Model is an object that stores persistent state.

Features:
 a. Models are not directly displayed to the users, however template takes care of displaying them in HTML format.
 b. Models are usually loaded/updated with data from/to the backend services asynchronously. However, model is agnostic to any backend/mockup adapters like Ember-Data, Ember-Model, Ember-Resource, etc.

Example: JS Bin example of the above points: (a, b)



Route

A route is an object that tells the template which model it should display.

Features:
 a. Route query's the model using model-hook, so that the model is available to template and its controller
 b. Route returns promise from model-hook, so one can implement a 'LoadingRoute' (i.e. a waiting state, which waits for the model to resolve asynchronously).
 c. Route can set controller properties
 d. Route can execute events and actions
 e. Route can connect any template to any controller

Example: JS Bin examples of the above points: (a, c), (b) & (d, e)


Controllers

A controller is an object that stores application state.

Features:
 a. A controller is in direct relation with a given template. However, controller is optional for a given template.
 b. Controller houses properties that are retrievable by its template.
 c. Receives a model from a Route
 d. Acts as a bridge between model and view/template
 e. Houses convenient methods (i.e. business-logic). For e.g. methods that switch between editing mode and normal mode. Methods such as 'goIntoEditMode()' and 'closeEditMode()'.
 f. Good to know! When a controller is not declared for a given template, then the Ember framework auto-generates a controller. For e.g. a user template with a 'UserRoute', without a 'UserController' implementation artifact (i.e. there is no need for a explicit business-logic), then the Ember will generate a controller internally (i.e. in memory). Ember Inspector extension for Chrome web-browser / Ember Inspector add-on for Firefox web-browser can enable you to track internally/explicitly created controllers.

Example: Tutorial covering Ember.js + Sails.js + PostgreSQL is an example of the above points: (a, b, c, d, e) & (f)


Views

Views represent visual elements of an application.

Features:
 a. Views are composition of Controller + Handlebars template + Route
 b. Views generate events and enable interactions with visual elements
 c. Views comes with a collection of native hooks, such as 'didInsertElement' hook, used for implementing complex interaction using jQuery
 d. View composition facilitates reusability, such as modals, popovers, date-pickers & autocomplete fields.

Example: Tutorial covering Ember.js + Sails.js + PostgreSQL is an example of the above points: (a, c) & (b, d)


Helpers 

Helpers refers to Handlebars helpers.

Features:
 a. A function that transform data just before rendering. For e.g., transformation of the following date/timestamp: Wed May 28 10:10:01 EEST 2014 => '28 May 2014'.

Example: JS Bin example of the above point: (a)


Reference:
 - An In-Depth Introduction To Ember.js
 - Alternatives to Ember Data
 - Emberjs (Offical Website)
 - Emberjs Core-concepts (Official Documentation)

Thursday, May 1, 2014

Basics of Grunt: A task runner that helps automate your bulid-processes in your web development project



This blog covers couple of "elementary" use-cases for Grunt task runner. That is to automate certain repetitive build-processes in your project. Here the build-processes refers to invoking transpiler, JavaScript files concatenation & its minification.
Presumptions:
  • CoffeeScript is used instead of regular JavaScript in your web development project
  • Node.js runtime is installed
  • npm package manager for Node.js is also installed
Table of contents

Grunt task runner installation

Running the below command will install Grunt globally (i.e. accessible to Node.js runtime):
$ sudo npm install grunt-cli -g


Use-case 1

Grunt task runner for automating transpilation


i. Create source code folders

Starting with an empty project folder, create these two folders in your project's root directory:
  • js
  • coffeescript

ii. Install Grunt into your project

In your project's root folder, run the below command:
$ npm install grunt

iii. Generate 'package.json' file

This 'package.json' is required by the npm package manager. Now, run the below command & answer the project related meta-data as you find fit:
$ npm init

iv. Create 'Gruntfile.js' file

Now, in the project's root folder, create the must needed 'Gruntfile.js' file, with following modules definition skeleton:
module.exports = function(grunt) {
    grunt.initConfig({});
    grunt.loadNpmTasks();
};

v. Install & configure CoffeeScript-to-JavaScript transpiler module

Now, with the help of npm, we install a Grunt module for CoffeeScript-to-JS transpilation, with the below command:
$ npm install grunt-contrib-coffee --save-dev
Now, in the above created 'Gruntfile.js' file add the following module-handling definitions:
module.exports = function(grunt) {
    grunt.initConfig({
        coffee: {
            options: {
                bare: true
            },
            scritps: {
               expand: true,
               flatten: true,
               cwd: 'coffeescript/',
               src: ['*.coffee'],
               dest: 'js/',
               ext: '.js'
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-coffee');
};
Now, in-order to run the transpiler against your project's CoffeeScript, run the below command:
$ grunt coffee

vi. Automate transpilation

Now, the following two steps are necessary to automate-the-invocation of CoffeeScript-to-JS transpiler:
NOTE! This transpilation takes place only for the modified source files by Grunt.
Step1: Install modules that help in auto-running
Install these modules 'grunt-contrib-watch' & 'grunt-newer' with the below command:
$ npm install grunt-contrib-watch grunt-newer --save-dev
Step2: Configure Gruntfile.js file
Add the below definitions to 'Gruntfile.js' file:
module.exports = function(grunt) {
    grunt.initConfig({
        coffee: {
            options: {
                bare: true
            },
            scritps: {
                expand: true,
                flatten: true,
                cwd: 'coffeescript/',
                src: ['*.coffee'],
                dest: 'js/',
                ext: '.js'
            }
        },
        watch: {
            options: {
                livereload: true
            },
            scritps: {
                files: ['coffeescript/*.coffee'],
                tasks: ['newer:coffee']
            }
       }
    });

    grunt.loadNpmTasks('grunt-contrib-coffee');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-newer');
};
Now, in-order to auto-run the transpiler against your project's CoffeeScript, run the below command:
$ grunt watch


Use-case 2

Grunt task runner for automating concatenation & minification


i. Create a distribution folder

Now, in the project's root folder, create the below folder:
  • distribution

ii. Install & configure Concatenation & Minification modules

Now, with the help of npm, install the below two Grunt modules. These modules can concatenate JS files into a single-file & minify it. So, in-order to install these two modules run this command:
$ npm install grunt-contrib-concat grunt-contrib-uglify --save-dev
Add the below definitions to 'Gruntfile.js' file:
module.exports = function(grunt) {
    grunt.initConfig({
        coffee: {
            options: {
                bare: true
            },
            scritps: {
               expand: true,
               flatten: true,
               cwd: 'coffeescript/',
               src: ['*.coffee'],
               dest: 'js/',
               ext: '.js'
            }
        },
        watch: {
            options: {
                livereload: true
            },
            scritps: {
                files: ['coffeescript/*.coffee'],
                tasks: ['newer:coffee']
            }
        },
        concat: {
            dist: {
                src: ['js/*.js'],
                dest: 'distribution/js/all.js'
            }
        },
        uglify: {
            dist: {
                options: {
                    banner: '/* Project-Template Shaped With Grunt Task Runner by Nash | May 2014 */\n'
                },
                files: {
                    'distribution/js/all.min.js': ['distribution/js/all.js']
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-coffee');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-newer');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
};
Validate the above definitions does work by running these commands:
$ grunt concat
$ grunt uglify

iii. Automate build-sequence

Now, automating the invocation of the following build-sequence by Grunt: Transpilation-> Concatenation-> Minification of source files.
Configure Gruntfile.js file
Add the below definitions to 'Gruntfile.js' file in-order help setup the build-sequence:
module.exports = function(grunt) {
    grunt.initConfig({
        coffee: {
            options: {
                bare: true
            },
            scritps: {
               expand: true,
               flatten: true,
               cwd: 'coffeescript/',
               src: ['*.coffee'],
               dest: 'js/',
               ext: '.js'
            }
        },
        watch: {
            options: {
                livereload: true
            },
            scritps: {
                files: ['coffeescript/*.coffee'],
                tasks: ['autobuild-with-minification']
            }
        },
        concat: {
            dist: {
                src: ['js/*.js'],
                dest: 'distribution/js/all.js'
            }
        },
        uglify: {
            dist: {
                options: {
                    banner: '/* Project-Template Shaped With Grunt Task Runner by Nash | May 2014 */\n'
                },
                files: {
                    'distribution/js/all.min.js': ['distribution/js/all.js']
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-coffee');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-newer');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask('autobuild-with-minification', ['newer:coffee', 'concat', 'uglify']);
    grunt.registerTask('default', ['coffee', 'concat', 'uglify', 'watch']);
};
Now, in-order to auto-run build-sequence, such as Transpilation-> Concatenation-> Minification, run the below command:
$ grunt
NOTE! You can further minify your JS file, if your 'Gruntfile.js' definition does not include this definition under 'coffee':
options: {
   bare: true
}


External references

Tuesday, August 20, 2013

Project Seed for ASP.Net WebAPI + AngularJS + Bootstrap

Project Seed: A 'ToDo' app built with MS ASP.Net WebAPI + MSSQL + AngularJS + Bootstrap

Poorman's Development Environment:
- Windows XP SP3
- MS Visual Studio Web Developer 2010 Express SP1 + 'Package Manager Console'
- MS SQL Server 2008 R2
- MS SQL Server Management Studio 2008 R2 10.50.1617.0
- MS .NET Framework 2.0.50727.3649


A. Restful API: Setting up ASP.Net WebAPI project

0. Steps to create a ASP.Net WebAPI project with Visual Studio:
i. File > New Project... > Visual C# > Web > ASP.NET MVC 4 Web Application
ii. Name: ToDoApp_WebAPI_MSSQL_AngularJS and click OK
iii. Select a template: Web API (Note! View engine: Razor)

1. JSON as primary data-exchange format: Paste the below code in the member function 'Register' present in the following class file 'WebApiConfig.cs'.

// Remove default XML data-exchange format, so as to use JSON
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"));
             
2. The Model: Now, create the ToDo's data-model class in the 'Models' folder, for example a class file called '/Models/ToDoItem.cs':

namespace ToDoApp_WebAPI_MSSQL_AngularJS.Models
{
    public class ToDoItem
    {
        public int ToDoItemID { get; set; }
        public String ToDo { get; set; }
        public byte Priority { get; set; }
        public DateTime? DueDate { get; set; }
    }
}

3. Importantly! Clean your project & Rebuild your project

4. Create controller class for the above created data-model in the 'Controllers' folder. Which will automatically creates set of default Restful resources + Database tables on MSSQL DB.

i. Controller Name: 'ToDoController'
ii. Template: API controller with read/write actions, using Entity Framework
iii. Model class: ToDoItem (ToDoApp_WebAPI_MSSQL_angularJS.Models)
iv. Data context class: <New data context...> ToDoApp_WebAPI_MSSQL_AngularJS.Models.ToDoContext

5. Now, run the project & test your web app on your faviourate web-browser. For example with this URL:
http://localhost:????/api/todo


B. Pseudo dataset: Generate pseudo dataset on MSSQL database

1. Enable-Migrations with the database using the "Package Manager Console". Which will create a 'Configuration.cs' after creating a detected Database for your application.

2. Now, Add your logic for generating pseudo dataset using your data-model in "Configuration.cs", as below:

protected override void Seed(ToDoApp_WebAPI_MSSQL_AngularJS.Models.ToDoContext context)
        {
            var r = new Random();
            var items = Enumerable.Range(1, 15).Select(o =>
                            new ToDoItem
                            {
                                ToDo = o.ToString(),
                                Priority = (byte)r.Next(10),
                                DueDate = new DateTime(2012, r.Next(1,12), r.Next(1,28))
                            }
                        ).ToArray();
            context.ToDoItems.AddOrUpdate(item => new { item.ToDo }, items);
        }
     
3. Now, run Update-Database command in "Package Manager Console" in-order to inject random dataset to MSSQL database.

4. Now, run the Project & test your web app on a web-browser. For example with this URL:
http://localhost:????/api/todo


C. Frontend: AngularJS + Bootstrap setup  

1. With the help of "Package Manager Console", download the necessary libraries for your frontend:
i. Install-Package angularjs
ii. Install-Package Twitter.Bootstrap

2. Importantly! Clean your project & Rebuild your project

3. Create an 'index.html' file in the projects root directory, using the below html:

<!DOCTYPE html>
<html ng-app="ToDoApp" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="Scripts/jquery-1.9.1.js"></script>
<script src="Scripts/bootstrap.js"></script>
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-resource.js"></script>
<script src="Scripts/app.js"></script>
<link rel="stylesheet" type="text/css" href="Content/bootstrap/bootstrap.css" />
<title>Amazing Todo</title>
</head>
<body>
<div class="container">
<div ng-view></div>
</div>
</body>
</html>

4. Create an 'app.js' file in the '/Scripts' directory, using the below content:

//Constructor
var ToDoApp = angular.module('ToDoApp', ['ngResource']).config(
function ($routeProvider) {
$routeProvider.
when('/', { controller: ListController, templateUrl: 'list.html' }).
otherwise({ redirectTo: '/' });
}
);

//Factory for configuring the DB query
ToDoApp.factory('ToDo_Resource', function ($resource) {
return $resource(
'/api/todo/:id',
{ id: '@id' },
{ update: { method: 'PUT'} }
);
});

//Controller
var ListController = function ($scope, $location, ToDo_Resource) {
$scope.items = ToDo_Resource.query();
};

5. Create a 'list.html' file in the projects root directory, using the below bootscrap components:

<table class="table table-striped table-condensed table-hover">
    <thead>
        <th>
            ToDo's
        </th>
        <th>
            Priority
        </th>
        <th>
            DueDate
        </th>
    </thead>
    <tbody>
        <tr ng-repeat="item in items">
            <td>
                {{item.ToDo}}
            </td>
            <td>
                {{item.Priority}}
            </td>
            <td>
                {{item.DueDate | date:mediumDate}}
            </td>
        </tr>
    </tbody>
</table>

6. Now, run the Project & test your web app on a web-browser. For example with this URL:
http://localhost:????/index.html


Seed mercurial-repository:
This entire project-seed can be cloned from Bitbucket, here's the repository's URL:
https://bitbucket.org/nshetty/todoapp_asp.netwebapi_mssql_angularjs_bootstrap

Related references:

Tuesday, December 4, 2012

Part1 - Can Gevent and Socket.IO be an event-driven, asynchronous IO/Networking infrastructure for building near-realtime web applications, keeping code-ability at the centre of it?

Keywords: Event-driven architectural style, Asynchronous IO/Networking, Gevent a Python based event library, Socket.IO comet library, Near-realtime web application

An important question while choosing a technology stack for an event-driven architecture (i.e. problem domain) is:
What is the programming paradigm that would be programmer friendly? [Note! Programmer friendly refers to "lities" like code maintainability, code scalability, code testability, among others.]

The status quo for implementing event-driven infrastructure is => to use call-backs. Of-course, devil is in the details... call-backs have their +ves, but lots of -ves (references: 1, 2) when we seek for the above mentioned "lities". 

Instead, think about... what if programmers could use imperative programming style to tackle this problem domain. Well, the solution don't lie in shifting of programming paradigm itself, but in the possibility to isolate recurring implementation details like call-backs. This gets us to acknowledging the power of DRY principle. Perhaps, what if such a DRY princip can be released with a set of programming language features:
    • Automatically takes care of creating call-backs
    • Creation of a call-back is dependent on a given routine, that is if a routine acts as blocking-type (i.e. blockage of the control flow)
    • Possibility to manually declare blocking-type routines
  Gevent API for Python is such an attempt to incorporate the above mentioned DRY princip into the programming language. In addition, as a side effect this API achieves a clear cut imperative programming style. Which means that call-backs are implicitly present but also make room for explicit declaration where needed.

Importantly, I am already smelling the "lities" being satisfied... is it? Well, in-order to answer this question... it will take some experimenting with the Gevent API. I hope this will be a path to enlightenment and to be convinced of this API friendliness towards code-ability.

Upcoming post will produce a simple prototype which will bring all the above mentioned technology stack and study it further. Here's heads-up to the prototype's repository.