Rapid Prototyping with MEAN Stack – NodeJS – Express



Rapid Prototyping with MEAN Stack – NodeJS – Express

0 4


DeveloperWeek-Mean

Developer Week 2015

On Github Yonet / DeveloperWeek-Mean

Rapid Prototyping with MEAN Stack

Aysegul Yonet / @AysegulYonet

http://bit.ly/DeveloperWeekMean

What we will use

What is MEAN?

Cons: You have to manage memory leaks, keep in mind CPU-bound computations off the event loop and be very careful with exception handling.

What we will build

Oscar Nominees Voting Form

  • Login
  • Voting for nominees
  • Create Schemas for our database
  • Submit and retrieve data from the database

What you need to install

  • Node.js website/
    brew install node
    							
  • Yeoman
    npm install -g yo bower grunt-cli gulp
    							
  • MongoDB
    brew update
    brew install mongodb
    //or
    brew install mongodb --with-openssl
    							

Running MongoDB for the first time

Create a /data/db directory

mkdir -p /data/db
					

Make sure you have read/write access to the data directory.

sudo chmod 777 /data/db
					

To run the database

mongod
					

To access the database, run mongo in a new terminal window

mongo
					
More info. ls la to see the permission. The r, w, and x specify the read, write, and execute access, respectively.

Mean Stack without generators

Because the generated is made by experienced developers, they applies good practices in code organisation and style programming (like the environment configuration on the server side using node).

Step-0

Angular Full-Stack Generator

  • Install generator globally.
    npm install -g generator-angular-fullstack
    							
  • Make a new directory and cd into it.
    mkdir my-new-project && cd $_
    							
  • Create your app with the generator.
    yo angular-fullstack [app-name]
    							
  • Generator will install your dependencies.
    npm install && bower install
    							
  • Run MongoDB in another terminal window.
    mongod
    							
  • Run your Grunt server
    grunt serve
    							
npm cache clean, bower cache clean. Note the file structure.

NodeJS

Core Modules

Unlike other programming technologies, Node.js doesn’t come with a heavy standard library. The core modules of node.js are a bare minimum, and the rest can be cherry-picked via the NPM registry. 60,000+ npm modules.

Non Core Modules

http

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
						

Launch

node server
						
This snippet creates a server with a callback function which contains the response handler code. The req and res arguments have all the information about a given HTTP request and response correspondingly.

Express

Enriches node’s native HTTP/HTTPS

Simple express server.

var express = require(express);
var app = express();

app.get('/', function(req, res) {
	res.sendFile(__dirname + '/client/index.html');
});

var server = app.listen(3000, function () {
  var host = server.address().address
  var port = server.address().port
  console.log('Example app listening at http://%s:%s', host, port)
});
						
node server
						
Middleware is a function with access to the request object (req), the response object (res), and the next middleware in line in the request-response cycle of an Express application, commonly denoted by a variable named next. Middleware can: Execute any code. Make changes to the request and the response objects. End the request-response cycle. Call the next middleware in the stack.

Step-1

MongoDB

NoSQL Document Database

  • Dynamic Schema
  • Binary JSON

More than that...

Full Index support, MapReduce and Aggregation, Scale and availablity...

Mongoose

Elegant mongodb object modeling for node.js

npm install mongoose
						
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var Cat = mongoose.model('Cat', { name: String });

var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
  if (err) // ...
  console.log('meow');
});
						

Mongoose’s schema setup is defined by 3 types:

  • Schema
  • Connection
  • Model

Schema

A Schema is an object that defines the structure of any documents that will be stored in your MongoDB collection; it enables you to define types and validators for all of your data items.

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

Connection

A Connection is a fairly standard wrapper around a database connection.

Model

A Model is an object that gives you easy access to a named collection, allowing you to query the collection and use the Schema to validate any documents you save to that collection.

A model is a class with which we construct documents. We can access all of the kitten documents through our Kitten model.
var Mongoose = require('mongoose');
var myConnection = Mongoose.createConnection('localhost', 'mydatabase');

var MySchema = new Mongoose.schema({
name : {
    type : String,
    default : 'Val',
    enum : ['Val', 'Valeri', 'Valeri Karpov']
  },
created : {
    type : Date,
    default : Date.now
  }
});

var MyModel = myConnection.model('mycollection', MySchema);
var myDocument = new MyModel({});
					
MongoDB uses named collections of arbitrary objects, and a Mongoose JS Model abstracts away this layer. Because of this, we don’t have to deal with tasks such as asynchronously telling MongoDB to switch to that collection, or work with the annoying createFromHexString function.

Functions added to the methods property of a schema get compiled into the Model prototype and exposed on each document instance

// NOTE: methods must be added to the schema before compiling it with mongoose.model()
kittySchema.methods.speak = function () {
  var greeting = this.name
    ? "Meow name is " + this.name
    : "I don't have a name"
  console.log(greeting);
}

var Kitten = mongoose.model('Kitten', kittySchema)
						

To find all of our kittens:

Kitten.find(function (err, kittens) {
  if (err) return console.error(err);
  console.log(kittens)
});
						

To find specific ones:

Kitten.find({ name: /^Fluff/ }, callback);
						

You can find the database info on "oscars/server/config/environment/development.js"

mongo
use oscars-dev
show collections //users, things
db.users.find() //to list all the users.
						

Best Practices

1 schema = 1 file

A schema should never be declared in app.js, and you should never have multiple schemas in a single file (even if you intend to nest one schema in another). While it is often expedient to inline everything into app.js, not keeping schemas in separate files makes things more difficult in the long run. Separate files lowers the barrier to entry for understanding your code base and makes tracking changes much easier. Mongoose can’t handle multi-level population yet, and populated fields are not Documents. Nesting schemas is helpful but it’s an incomplete solution. Design your schemas accordingly.

Passport

An authentication middleware for Node.js which supports authentication using a username and password, Facebook, Twitter, and more.

Angular

Parts that makes an Angular application

Built in directives

  • ngModel: Binding the view into the model.
  • ngRepeat: instantiates a template once per item from a collection
 //input value is bind to $scope.userName in the controller
{{key}} - {{value.name}}

Filters

yo angular-fullstack:filter truncate
						
angular.module('oscarsApp')
  .filter('truncate', function () {
    return function (text, length, end) {
      if (isNaN(length))
                length = 10;

            if (end === undefined)
                end = "...";

            if (text.length <= length || text.length - end.length <= length) {
                return text;
            }
            else {
                return String(text).substring(0, length-end.length) + end;
            }

        };
  });
  						

Angular Services

By Angular conventions, lowerCamelCase is used for factory names that won't be new'ed.

yo angular-fullstack:factory nomineesFactory
						
app.factory('nomineesFactory', [function(){
  var nominees = {
    categories:...
  };
  return nominees;
}]);
						

To use the factory in your controller:

app.controller('MainCtrl', ['$scope','nomineesFactory',
function($scope, nomineesFactory){
	$scope.categories = nomineesFactory.categories;
  ...
)};
						
Step-2

Deploying your app.

Heroku

OpenShift

More Resources

MongoDB Resources

Express Resources

Angular Resources

Node Resources

THE END

BY Aysegul Yonet / aysegulyonet@gmail.com

Come every Monday with your questions to Women Who Code/Girl Develop It Meetups @HackReactor