Adding custom validators in MongoDB+Mongoose

Today we’re going to add custom validators to some of our documents in Mongoose.

Things you’ll have to be familiar with for this article

  • MongoDB
  • Mongoose
  • Nodejs

Why make custom validators?

When dealing with data sent over the web we often find that the inputs we are given tend to be suboptimal. We need some way of relaying to our end users that they’re not meeting our input needs. This is where validators come in. We can define a function that will arbitrate what is and isn’t an acceptable input for a given field. To get started properly let’s define a model and give it a few fields.

const Mongoose = require('mongoose');
Mongoose.connect('mongodb://127.0.0.1/SomeDB',
{
  useNewUrlParser: true,//to get rid of annoying 
  useUnifiedTopology: true,//warning messages

});
//Now that we're connected let's make a user schema


const Schema = mongoose.Schema;
const HorseSchema = new Schema
({
  name:{type: String, required:true},
  color: 
  { 
    type: String, 
    required: true
  },
  bad:{type: Boolean, default: false},
   

});
Mongoose.model('user',UserSchema);//and model that bad boy in our DB

Now that we’ve laid out our schema we can add some validators. In this instance, we really don’t want folks to give us “green”, “magenta” or “rainbow” horses. To prevent this, we’ll implement a simple validator object that will check if our document’s color is a fit and if it does not contain our desired color it will complain with a provided reason.

ColorValidator =
{
  validator: function(documentColor) 
  {
    colors = ['red','brown','yellow','white','black']
    return colors.includes(documentColor);
  },
  message: 'Please select a valid color',
  reason: 'A non-normal color was provided'
}

const HorseSchema = new Schema
({
  name:{type: String, required:true},
  color: 
  { 
    type: String, 
    required: true,
    validate: ColorValidator
  },
  bad:{type: Boolean, default: false},
});

Mongoose.model('user',UserSchema);//and model that bad boy in our DB


That wraps up our tutorial. If you’re interested in extending this code yourself and implementing it in your own project, simply adapt the “validator” part of the ColorValidator object and shoehorn it into your own work.

Consuming Axios in a Vue + Vuex project

This tutorial focus will show you how to assimilate Axios into your tool belt for use in future projects to help save you time and headache.

Prereqs:

  • Basic knowledge of
    • Vue.Js
    • Vuex
    • Axios
  • A preexisting Vuejs app with Vuex

What are we doing and why?

We are taking the Axios plugin for Vuejs and baking it into our own custom GET, POST, PUT and DELETE functions for future projects in a scalable, reusable manner, that will help stop some bad smells from appearing in your code.

Getting Started

Make a new file called “CRUD.js” This is where we will store all of our CRUD functions. let’s create a basic “GET” wrapper for Axios with some minimal error handling.

import axios from "axios"

const GetFunction = async function(route,params,headers)
{
    try
    {
        var results = await axios.get(route,{params,headers});
        return results.data;    
    }
    catch(error)
    {
        return error.response.data;
    }
}
export const Get = GetFunction;

Doing this alone only gives us the benefit of our own custom error handling. Which is nice but we can do much better. In the app where this solution was ultimately handled, the headers from the website did not change between requests, neither did the route. All we have to do to exploit this is add a few lines to our code so we may remove a few arguments from this function call

import axios from "axios"
import store from '@/store/store'

const GetFunction = async function(params)
{
    var address = store.state.address; 
    var headers = store.state.headers;
    try
    {
        var results = await axios.get(address,{params,headers});
        return results.data;    
    }
    catch(error)
    {
        return error.response.data;
    }
    
}

But why?

Basically this eliminates some headache for us down the line. By referring to our state we can refer to our API backend and our token simply by calling our “Get” export from our module. In the event that our API’s address changes, such as when we have a different IP/address from development to deployment, we don’t need to change every single Axios call in our project. Simply change what our state for what the address is, and then we can move on to deployment with a great deal less of worry on our shoulders.