1. Building Simple CRUD API Calls
TL;DR - in CLI, type "plop" and select MSC
In api, there are four main folders developers will spend most of their time in: Controllers, Services, Models and App_Start. Controller handles the interpretation of URLs and its permissions. This means that whenever you want to provide a new URL path, you'll add it here. Services contains all the business logic and data-transfer-object (DTO) mapping, Model describes the database schema, and app_start are configuration method calls to be made at application start.
We will start off by building a recipe API. This API will have the following fields:
- name
- ingredients (array of:)
- name
- amount
- unit
Create a model
in CLI
$ plop
Plop is a generator for scaffolding files. With so many different developers working together, it is hard to maintain a sustainable structure without strongly opinionated best practices. A generator provides speed, as well as consistency in code.
In the list, select 'Model':
After, you will be greeted with a prompt for the model's name. Here, we will enter 'recipe':
VOILA! You've have just scaffolded your first model!
Notice how even though we typed in 'recipe' with all lowercase, the generator manages to capitalise the name for the filename, schema name and made collection plural. We leave the naming convention to the generator so we can have consistent code without requiring every developer to be aware of it. Plop supports spacing in name.
Now that we have the Recipe model scaffolded, let's add some structure to our database schema:
'use strict';
const mongoose = require('hexin-core/helpers/Database').getConnection();
const Schema = mongoose.Schema;
const IngredientSchema = new Schema({
name: {type: String, required: true},
amount: {type: Number, required: true, default: 1},
unit: {type: String, required: true}
}, {_id: false});
const RecipeSchema = new Schema({
name: {type: String, required: true},
ingredients: [IngredientSchema]
}, {collection: 'recipes'});
// Execute before each model.save() call
RecipeSchema.pre('save', function (callback) {
callback();
});
// Export the Mongoose model
module.exports = mongoose.model('Recipe', RecipeSchema);
A recipe will have a name to identify it by, and a list of ingredients required for this dish. In each ingredient, there is a name (ie. salt, ribeye, spaghetti), an amount and its unit for the amount (ie. cup, teaspoon)
Create the Service
in CLI
$ plop
Similar to Model, we'll use plop. This time, we'll select 'Service':
After, enter 'recipe' for name:
Lastly, you'll see that there is one more question this time. Our framework supports a wrapper for our service class to automatically implement the basic CRUD functions (get, getAll, create, update, delete). We will select 'y' (yes) to this:
Now we have a service ready for Recipe that'll provide the basic CRUD methods.
Create the Controller
in CLI
$ plop
So we are here again, I know. There is a better way though, just stay tuned for the goodies
This time, we'll select 'Controller':
Inside, we'll give it the same name as above; 'recipe':Similar to Service, we'll give a big thumbs up for CRUD:
Although CRUD controller does not have to rely on CRUD service, by default they go hand in hand. This means that there is no configuration required to get the basic CRUD methods going when installing using these two CRUD classes.
THERE! We have ourselves a Recipe schema, with the basic CRUD API calls available for external projects to use!
Same same, but FASTER, but same same!
So after going through the whole process above, you might say 'Hey, plop is great, it reduces a lot of copy&pasting time required. Issue is, can't we make it even faster? That was so repetitive!' Well, introducing our plop's latest model, the MSC (Model, Service, Controller)! It has 1500 horsepowers, and muffler that'll most definitely impress your father-in-law!
In CLI, we go back to plop:
$ plop
In here, go to the almighty 'MSC':
Here on, I think you know what to do:
AND BOOOM GOES THE DYNAMITE! You just did everything above with these few lines! Class dismissed! *Mic drops*