Search code examples
node.jsexpressmongoosemongoose-schemarestful-url

Repeating code for same operation of different datatypes, Express(nodejs) app with mongoose


I am creating an Express rest API that connects to a MongoDB with mongoose. The database has several different datatypes: User, Book, Food and so on. As I am writing endpoints and function for these datatypes. I realized that I am repeating a lot of the same code, for example, for the code below:

// Book.js
import Book from './models/Book'

function deleteById (req, res, next) {
  Book.findByIdAndRemove(req.params.id, function (err) {
    if (err) {
      let error = new Error('Failed to delete an book in database')
      error.statusCode = 500
      return next(error)
    }
    res.json({
      success: true,
      message: 'Book deleted successfully'
    })
  })
}

I can just change Book to User or Food and the same code can be used. Which results in a lot of repeating code that looks like this:

// Food.js
import Food from './models/Food'

function deleteById (req, res, next) {
  Food.findByIdAndRemove(req.params.id, function (err) {
    if (err) {
      let error = new Error('Failed to delete an food in database')
      error.statusCode = 500
      return next(error)
    }
    res.json({
      success: true,
      message: 'Food deleted successfully'
    })
  })
}

So I was wondering if there is a way to generate the functions so that I don't need to repeat the code for the deleteById function for each type of data. What would be the best practice? Or is it a bad practice to try to generate the functions and repeating is necessary?

Any help would be really appreciated, thanks in advance.


Solution

  • After a lot of research, I found the best way to be using a class constructor and pass in datatype as a variable:

    class BaseController {
      constructor (type, name) {
        if (!type || !access) {
          throw new Error('Must define datatype')
        }
        this.datatype = type
        this.name = name
        this.deleteById = this.deleteById.bind(this)
      }
    
      deleteById (req, res, next) {
        let name = this.name
        this.datatype.findByIdAndRemove(id, function (err) {
          if (err) {
            let error = new Error(`Failed to delete ${name} in database`)
            error.statusCode = 500
            return next(error)
          }
    
          res.json({
            success: true,
            message: `${name} deleted successfully`
          })
        })
      }
    }
    

    And in the router file, we can just call

    const food = new BaseController(Food, 'Food')
    router.get('/food/delete/:id', food.deleteById)