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.
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)