PJCHENder
4/10/2017 - 9:24 AM

[Express] Some boilerplate for Express

[Express] Some boilerplate for Express

const express = require('express')
const router = express.Router()

/**
 * SomeNote:
 * 因為在 app.js 中是套用 app.use('/qustions', routes),所以這個 router 的根目錄為 '/questions'
 */

// GET '/questions',Routes for question collection
router.get('/', (req, res) => {
  res.json({response: 'You send me a GET request'})    //  這會結束 req cycle
})

// POST '/questions',Routes for creating questions
router.post('/', (req, res) => {
  res.json({
    response: 'You send me a POST request',
    body: req.body
  })
})

// GET '/questions/:qID',Routes for specific question
router.get('/:qID', (req, res) => {
  res.json({
    response: 'You send me a GET request for ID ' + req.params.id
  })
})

// POST '/questions/:qID/answers,Routes for creating answers
router.post('/:qID/answers', (req, res) => {
  res.json({
    response: 'You send me a POST requst to /answers',
    questionId: req.params.qID,
    body: req.body
  })
})

// PUT '/questions/:qID/answers/:aID',Edit a specific answer
router.put('/:qID/answers/:aID', (req, res) => {
  res.json({
    response: 'You send me a PUT request to /answers',
    questionId: req.params.qID,
    answerId: req.params.aID,
    body: req.body
  })
})

// DELETE '/questions/:qID/answers/:aID',Delete a specific answer
router.delete('/:qID/answers/:aID', (req, res) => {
  res.json({
    response: 'You send me a DELETE request to /answers',
    questionId: req.params.qID,
    answerId: req.params.aID
  })
})

// Vote on a specific answer
// POST '/questions/:qID/answers/:aID/vote-up'
// POST '/questions/:qID/answers/:aID/vote-down'
router.post('/:qID/answers/:aID/vote-:dir', (req, res) => {
  res.json({
    response: 'You send me a POST request to /vote=' + req.params.dir,
    questionId: req.params.qID,
    answerId: req.params.aID,
    vote: req.params.dir
  })
})


module.exports = router
const mongoose = require('mongoose')

// -- 1. 和 mongoDB 連線 --
mongoose.connect('mongodb://localhost:27017/bookworm')
var db = mongoose.connection               //  將連線的物件儲存,並可監聽事件

// --  2. 處理連線錯誤的情況 --
db.on('error', (err) => {
  console.error('connection error:', err)
})

// --  3. 成功連線要執行的動作 --
db.once('open', () => {
  console.log('db connection successful')

  // All database communication goes here

  // -- 4.1 建立 Schema (用來描述 document) --
  var Schema = mongoose.Schema
  var AnimalSchema = new Schema({
    type: {
      type: String,
      default: 'notype'
    },
    size: {
      type: String,
      default: 'nosize'
    },
    color: {
      type: String,
      default: 'notype'
    },
    mass: {
      type: Number,
      default: 0
    },
    name: {
      type: String,       // 記得 S 大寫
      default: 'noname',  // 預設值
      required: true,     // 表示為必填欄位,若缺少此欄位,mongoDB 不會建立此 document 並會回傳 error
      trim: true,         // 去除掉不必要的空白
      unique: true        // 確認這個 email 的值沒有在其他 document 中出現過(也就是沒有相同的 email)
    }
  })

  // --4.2 可以為 Schema 添加 method(要在 compile 前),類似 instance method
  AnimalSchema.methods.getType = function () {
    // 這裡的 this 指透過這個 function constructor 建立的物件
    console.log('This animal is a/an', this.type)
  }

  AnimalSchema.methods.findSameColor = function (callback) {
    return this.model('Animal').find({color: this.color}, callback)
  }

  // --4.3 prehook
  AnimalSchema.pre('save', function (next) {
    // this 指稱的是要被儲存的 document
    // 記得不要用 arrow function
    if (this.mass >= 100) {
      this.size = 'big'
    } else if (this.mass >= 5 && this.mass < 100) {
      this.size = 'medium'
    } else {
      this.size = 'small'
    }
    next()
  })

  // --4.4 建立 statics method,類似 class method
  AnimalSchema.statics.findSize = function (size, callback) {
    // this 指稱的是 collection (Animal)
    // callback 表示找到之後要執行的動作
    return this.find({size: size}, callback)
  }

  // -- 5. Compile Schema 變成 Model --
  // 利用 AnimalSchema 來建立一個 model (用來建立和儲存 document)
  var Animal = mongoose.model('Animal', AnimalSchema)   // 它會在 mongo 中建立名為 animals 的 collections

  // -- 6. 建立 document --
  // 利用 Animal 建立 animal documnet
  var elephant = new Animal({
    type: 'elephant',
    size: 'big',
    color: 'gray',
    mass: 6000,
    name: 'Lawrence'
  })
  // console.log(elephant.type)   //  'elephant'
  // elephant.getType()           //  'This animal is a/an elephant'

  var whale = new Animal({
    type: 'whale',
    size: 'big',
    color: 'blue',
    mass: 6000,
    name: 'Whawha'
  })

  var goldfish = new Animal({})  // 以預設值建立一筆資料

  // 一次建立多筆 documents
  var animalData = [
    {
      type: 'mouse',
      color: 'gray',
      mass: 0.034,
      name: 'Marvin'
    },
    {
      type: 'nutria',
      color: 'brown',
      mass: 6.35,
      name: 'Gretchen'
    },
    {
      type: 'wolf',
      color: 'gray',
      mass: 45,
      name: 'Iris'
    },
    elephant,
    whale,
    goldfish
  ]

  // 透過 remove 刪除 collection 中的所有 document,
  // 由於 remove 也是非同步的,因此我們要把 save 放到 callback 中
  // 1. 先刪除 collcetion 中的所有 documents
  Animal.remove({}, () => {
    console.log('removed successed')
    // 2. 一次儲存多筆 document
    Animal.create(animalData, (err, animals) => {
      // 3.1 利用 instance method 列出和 elephant 相同顏色的動物
      if (err) console.log(err)
      Animal.findOne({type: 'elephant'}, function (err, elephant) {
        if (err) console.log(err)
        elephant.findSameColor(function (err, animals) {
          if (err) console.log(err)
          console.log('findSameColor', animals)
          db.close(() => {
            console.log('db closed')
          })
        })
      })
      // 3.2 利用 statics method 列出 {size: 'big'} 的 document
      // Animal.findSize('big', (err, animals) => {
      //   if (err) console.log(err)
      //   animals = animals.map((animal) => {
      //     return ({name: animal.name, type: animal.type, size: animal.size})
      //   })
      //   console.log(animals)
      //   // 4. 關閉連線
      //   db.close(() => {
      //     console.log('db connection closed')
      //   })
      // })
    })
  })
})
const express = require('express')
const app = express()
const routes = require('./routes')
const jsonParser = require('body-parser').json
const logger = require('morgan')

app.use(jsonParser())
app.use(logger('common'))  // 給我們 prettify 後的 logger
app.use('/questions', routes)   //  這個 middleware 只處理來自 '/questions'


/**
 * Get request and send response 
**/

**
 * Demo for get data from GET and POST
 */

const express = require('express')
const app = express()
const jsonParser = require('body-parser').json

app.use(jsonParser())

app.use((req, res, next) => {
  console.log(req.body.color)                  // req.body 可以取得 POST 的 body(但要先 parser 過)
  next()
})

app.use((req, res, next) => {
  req.myMessage = 'Hello, middleware 2'        // send variable to other middleware
  next()
})

app.use((req, res, next) => {
  console.log('color', req.query.color)        // req.query 可以取得 URL ? 後的內容
  next()
})

app.use((req, res, next) => {
  console.log(req.myMessage)                   // get variable from previous middleware
  next()
})

app.use('/different/:id', (req, res, next) => {
  console.log(req.params.id)                  // req.params.id 可以取得 URL 中的參數(:variable)
  next()
})


// catch 404 and forward to error handler
app.use((req, res, next) => {
  let err = new Error('Not found (404)')
  err.status = 404
  next(err)   //  將錯誤訊息傳送給 error handler
})

// Error Handler
app.use((err, req, res, next) => {
  res.status(err.status || 500)    //  如果有給 err.status 則顯示,否則顯示 500(internal server error)
  res.json({
    error: {
      message: err.message
    }
  })
})

//  Listen for the server
const port = process.env.PORT || 3000
app.listen(port, () => {
  console.log('Express is listening on port ' + port + ' ...')
})