0
\$\begingroup\$

What my code does

I am building an Express API server with mongoDB as my database.

I have a list of players which must be added to 2 mongoDB collections (teamList and countryList).

The data schema is similar. My code is as follows.

Data Model model.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var teamSchema = new Schema({
  teamid: {
    type: String,
    required: true
  },
  created: {
    type: Date
  },
  lastUpdated: {
    type: Date,
    default: Date.now,
    required: true
  },
  playerList: [{
    name: {
      type: String,
      required: true,
      unique: true
    },
    dateAdded: {
      type: Date,
      default: Date.now
    }
  }]
});

module.exports = mongoose.model('teamModel', teamSchema);


var countrySchema = new Schema({
  countryid: {
    type: String,
    required: true
  },
  created: {
    type: Date
  },
  lastUpdated: {
    type: Date,
    default: Date.now,
    required: true
  },
  playerList: [{
    name: {
      type: String,
      required: true,
      unique:true
    },
    dateAdded: {
      type: Date,
      required: true
    }
  }]
});
module.exports = mongoose.model('countryModel', countrySchema);

Router router.js

module.exports = function(app) {
  const teamControllerv1 = require('../v1/controller/teamController');
  const countryControllerv1 = require('../v1/controller/countryController');  
  app.route('/v1/team').post(teamControllerv1.addPlayerToTeam);
  app.route('/v1/country').post(countryControllerv1.addPlayerToCountry);
};

Controllers countryController.js

var mongoose = require('mongoose');
const countryModel = mongoose.model('countryModel');

exports.addPlayerToCountry = function (req, res) {
    countryModel.update({
        countryid: req.body.countryID
      }, {
        $addToSet: {
          countryList: {
            $each: req.body.playerList
          }
        }
      }, {
        upsert: true
      },
      function (err, data) {
        if (!err && data) {
          util.successResponder(res, successText);
        } else {
          util.serverErrorResponder(res, errorOccured);
        }
      });
}

teamController.js

var mongoose = require('mongoose');
const TeamModel = mongoose.model('teamModel');

exports.addPlayerToTeam = function (req, res) {
    teamModel.update({
        teamid: req.body.teamID
      }, {
        $addToSet: {
          teamList: {
            $each: req.body.playerList
          }
        }
      }, {
        upsert: true
      },
      function (err, data) {
        if (!err && data) {
          util.successResponder(res, successText);
        } else {
          util.serverErrorResponder(res, errorOccured);
        }
      });
}

Problem I am trying to solve

As you can see this code clearly violates DRY. Except the mongoose database connector, everything else in the 2 files is exactly the same. How can I write this in a cleaner way such that the db connector is abstracted away?

\$\endgroup\$
  • 1
    \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How to Ask for examples, and revise the title accordingly. \$\endgroup\$ – Mast Jul 13 '18 at 9:02
  • \$\begingroup\$ @Mast Thanks for pointing it out. I agree. I have edited the title to be more descriptive. \$\endgroup\$ – Sashi Jul 13 '18 at 9:06
  • 1
    \$\begingroup\$ The site standard is for the title to simply state the task accomplished by the code. Leave the concerns for the question body. \$\endgroup\$ – Mast Jul 13 '18 at 9:15
1
\$\begingroup\$

So I kind of figured this out. The db connector can be passed around like just another variable. Silly I didn't realise this before. I created a new file to abstract the model.

dbOperations.js

exports.addToDB = async function (model, dataObj, listName, res) {
  model.update({
      userid: dataObj.userID
    }, {
      $addToSet: {
        listName: {
          $each: dataObj.playerID
        }
      }
    }, {
      upsert: true
    },
    function (err, data) {
      if (!err && data) {
        util.successResponder(res, successText);
      } else {
        util.serverErrorResponder(res, errorOccured);
      }
    });
};

teamController.js

var mongoose = require('mongoose');
const teamModel = mongoose.model('teamModel');
const dbOperations = require('../../helper/dbOperations');

exports.addPlayerToTeam = function (req, res) {
  let dataObj = {teamID: req.body.teamID, playerID: req.body.playerList};
  dbOperations.addToDB(teamModel,dataObj,'teamList',res);
}

And similarly for the other file as well. Any other files which follow a similar schema can use it. There is probably a better way to do this so that this can be generalised further to accommodate other schema types.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.