'How to Access a Field in Array of Objects With Joi Fork Method?
I am trying to write a reusable validation schema and I can change the rules of fields if I need it. I do this using a method called a fork. However, this time I couldn't imagine how can I access and change the rule of an object inside of an array. In some cases, some fields must be required. So I call the changed schema the default schema with the validation method. I am using this solution for a few models and generally, it works perfectly. Can you help me to imagine how can I solve this problem?
In this model, I have a subdocument field. This field is an array of objects field. That's why I have 2 different schemas. When the create method calls, I just need the title, description, and category object fields. If a user wants to add a question to the quiz record, I need a question array.
I was thinking that I can write a validator for only the question schema but if I don't add a field to the quiz validation schema then joi throws an error with the message "ABC field not allowed". I'm stuck because of this situation and I can't continue.
Quiz Model and Validation Schema and Method
const Joi = require('joi');
const mongoose = require('mongoose');
const slugCreator = require('mongoose-slug-updater');
mongoose.plugin(slugCreator);
const QuestionSchema = mongoose.Schema({
questionText: {
type: String,
trim: true,
minLength: 10
},
firstChoiceText: {
type: String,
trim: true,
minLength: 1
},
firstChoiceIsTrue: {
type: Boolean
},
secondChoiceText: {
type: String,
trim: true,
minLength: 1
},
secondChoiceIsTrue: {
type: Boolean
},
thirdChoiceText: {
type: String,
trim: true,
minLength: 1
},
thirdChoiceIsTrue: {
type: Boolean
},
fourthChoiceText: {
type: String,
trim: true,
minLength: 1
},
fourthChoiceIsTrue: {
type: Boolean
}
}, { timestamps: true });
const QuizSchema = mongoose.Schema({
title: {
type: String,
required: true,
trim: true,
minLength: 15,
maxLength: 250
},
description: {
type: String,
requried: true,
trim: true,
minLength: 50
},
coverImage: {
type: String,
trim: true
},
slug: {
type: String,
unique: true,
trim: true,
slug: ['title'],
slugPaddingSize: 3
},
category: {
title: {
type: String,
trim: true,
required: true
},
categoryId: {
type: mongoose.Types.ObjectId,
trim: true,
required: true
},
slug: {
type: String,
trim: true,
required: true
}
},
questions: [QuestionSchema],
createdBy: {
userId: {
type: mongoose.Types.ObjectId,
required: true
},
fullName: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
trim: true
}
},
updatedBy: {
userId: {
type: mongoose.Types.ObjectId,
required: true
},
fullName: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
trim: true
}
}
}, { collection: 'quizzes', timestamps: true });
const validationSchema = {
title: Joi.string().trim().min(15).max(250),
description: Joi.string().trim().min(50),
coverImage: Joi.string().trim(),
slug: Joi.string().trim(),
category: {
title: Joi.string().trim(),
categoryId: Joi.string().trim(),
slug: Joi.string().trim()
},
questions: Joi.array().items(
Joi.object({
questionText: Joi.string().trim().min(10),
firstChoiceText: Joi.string().trim().min(1),
firstChoiceIsTrue: Joi.boolean(),
secondChoiceText: Joi.string().trim().min(1),
secondChoiceIsTrue: Joi.boolean(),
thirdChoiceText: Joi.string().trim().min(1),
thirdChoiceIsTrue: Joi.boolean(),
fourthChoiceText: Joi.string().trim().min(1),
fourthChoiceIsTrue: Joi.boolean(),
})
),
createdBy: {
userId: Joi.string().trim(),
fullName: Joi.string().trim(),
email: Joi.string().email().trim()
},
updatedBy: {
userId: Joi.string().trim(),
fullName: Joi.string().trim(),
email: Joi.string().email().trim()
}
};
QuizSchema.statics.joiValidationForQuizCreate = async (quizObject) => {
const requiredSchema = Joi.object(validationSchema).fork(['title', 'description', 'createdBy.userId', 'createdBy.fullName', 'createdBy.email', 'updatedBy.userId', 'updatedBy.email', 'updatedBy.email'], item => item.required());
return await requiredSchema.validateAsync(quizObject);
};
module.exports = mongoose.model('quiz', QuizSchema);
I want to access these Question fields using the Fork method as in the joiValidationForQuizCreate method. Is this possible or is there a better method available? I don't want to write schematics over and over on a case-by-case basis.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
