Skip to content

Latest commit

 

History

History
319 lines (291 loc) · 7.91 KB

README.md

File metadata and controls

319 lines (291 loc) · 7.91 KB

expressSimpleBlog

Simple Blog example with Express, Jade, Mongoose

This example covers following topics;

  • express
  • mongoose
  • jade
  • session
  • schema decoration
  • security
  • routes
  • ideal project structure

Quick links ;

mongoose express jade

Basic express installation

  npm install -g express
  
  express
  
  create : .
     create : ./package.json
     create : ./app.js
     create : ./public
     create : ./public/javascripts
     create : ./public/images
     create : ./public/stylesheets
     create : ./public/stylesheets/style.css
     create : ./routes
     create : ./routes/index.js
     create : ./routes/user.js
     create : ./views
     create : ./views/layout.jade
     create : ./views/index.jade
  
     install dependencies:
       $ cd . && npm install
  
     run the app:
       $ node app

Schema examples

###Single

  User = new Schema({
        name:{
            type:String,
            required:false,
            default: ""
        },
        username:{
            type:String,
            validate:[validator({
                length:{
                    min:3,
                    max:20
                }
            }), "username"],
            required:false,
            default: "defaultusername"
        },
        password:{
            type:String,
            required:true
        },
        email:{
            type:String,
            required:true
        },
        registerDate:{
            type:Date,
            required:true,
            default: Date.now
        },
        loginDate:{
            type:Date,
            required:false
        }
    });

###Embedded

  Comment = new Schema({
        text:{
            type:String,
            required:true
        },
        author:{
            type:String,
            validate:[validator({
                length:{
                    min:3,
                    max:20
                }
            }), "username"],
            required:false,
            default:"anonymous"
        },
        createDate:{
            type:String,
            required:false,
            default: Date.now
        }
    });

    Blog = new Schema({
        title:{
            type:String,
            required:true
        },
        text:{
            type:String,
            required:true
        },
        author:{
            type:String,
            validate:[validator({
                length:{
                    min:3,
                    max:20
                }
            }), "username"],
            required:false,
            default:"anonymous"
        },
        comments: {type: [Comment]},
        createDate:{
            type:Date,
            required:false,
            default: Date.now
        }
    });

##Mongoose best practises ###1 Find specific user by username

  Model.findOne({username: "johndoe"}, function(err, userName) {
    if (err) {
      next("technical error occured");
    } else {
      if (userInfo) {
        next("User details : " + userInfo);
      } else {
        next("User not found")
      }
    }
  });

###2 Find users have age under 18 and sort them desc

  var query = Model.find({age: {$lt: 18}}).sort({age: -1});
  query.execFind({}, function(err, users) {
    if (err) {
      next("Technical error occured");
    } else {
      if (users) {
        next("How could you registered to my system? You will be banned one by one!!!");
        users.forEach(function(user) {
          user.status = "banned";
          user.save(function(err) {
            if (err) {
              next("Technical error occured while banning user : " + user);
            } else {
              next("Go find another buggy system to yourself!!!");
            }
          });
        })
      } else {
        next("System has no security vulnerability:)")
      }
    }
  });

###3 Insert subdocument

  Model.findOne({username: "johndoe"}, function(err, userInfo) {
    if (err) {
      next("Technical error occured");
    } else {
      if (userInfo) {
        var SubModel = new SubModel();// Assumed to be initialized somewhere above in the sky
        SubModel.projectName = "SocialAuth";
        SubModel.projectLanguage = "PHP";
        SubModel.projectCost = 100;
        userInfo.projects.push(SubModel);
        userInfo.save(function(err) {
          if (err) {
            next("Technical error again.What a stable system i am");
          } else {
            next("New project experience added to user : " + userInfo.username);
          }
        });
      }
    }    
  });

###4 Update subdocument

  Model.update(
            {
                username: "johndoe", project.name: "SocialAuth"
            },
            {
                $inc: {'projects.$.cost': 200}
            },
            //In order to update all documents. If you set this false, it will update only first found document
            {multi: true},
            function(err, result) {
              if (err) {
                next("Technical error occured");
              } else {
                next("Project finished its first year so i am updating its price as 200$ :)");
              }
            
            }

MongoDB credentials setup for project

In this project some user authentication methods have been used, so you can seup your mongodb user for your db;

  mongo localhost

  use <blog>

  db.addUser("test", "123456")

Added user test for b blog. This will be used in project config

Nested functions to waterfall

In express applications, there is a view problem on nested functions. Let's eee it in an example;

  Model1.findOne({username: "johndoe"}, function(err, userInfo) {
    if (err) {
      ........
    } else {
      Model2.find({age: userInfo.age}, function(err, model2Info) {
        if(err) {
          ......
        } else {
          Model3.find({something: model2Info.count}, function(err, model3Info) {
            if (err) {
              ........
            } else {
              .................
              ............
              ..............
              //4 more nested function
              Model8.find({}, function(err, someInfo) {
                if(err) ............
                else
                  next("I have found the result but i don't want to use this result because of this nasty nested function!!!");
              });
            }
          });
        }
      });
    }
  });

In real projects, there are such cases, so our hero on this case is;

step or async

I prefer async, because i used them and async wins :) async also has 3466 stars but step has 1091. There are several ways to re-implement above nested function by using async. We can use waterfall model(For more info please refer to project github documentation)

  async.waterfall([
    function(callback) {
      Model1.findOne({username: "johndoe"}, function(err, userInfo) {
        callback(null, userInfo);
      });    
    },
    function(userInfo, callback) {
      Model2.find({age: userInfo.age}, function(err, model2Info) {
        callback(null, model2Info);
      
      });
    },
    function(model2Info, callback) {
      Model3.find({something: model2Info.count}, function(err, model3Info) {
        var dummy = 15;
        callback(null, model3Info, dummy);
      });
      
    },
    function(modelInfo, count, callback) {
      var some = foo(modelInfo, count);
      callback(null, some);
    },
    ..........................
    ......................
    ,
    function(modelInfo, callback) {
      callback(null, modelInfo);  
    }
    ], function(err, result) {
      if (err) .......
      else
        next("Result found and i am happy to use this result");
    });