Security News
ESLint is Now Language-Agnostic: Linting JSON, Markdown, and Beyond
ESLint has added JSON and Markdown linting support with new officially-supported plugins, expanding its versatility beyond JavaScript.
require-topmodel
Advanced tools
RequireJS model injector
Please, read this documentation like a novel... it's not really written like an API reference, but more like a story and I apologize for that. It is indeed quite complicated to just jump to a part and try to understand it.
Actually, it is also difficult to read it from the beginning to the end and try to understand it :-o
And I apologize for that...
For a browser usage, install with bower
bower install --save require-topmodel
For a server usage, install with node
npm install --save require-topmodel
You must define your models the requireJS way (AMD-style), even if you plan to use it server-side.
Let's say I have a Car model, looking like this and saved in a car.js file.
I use lodash as a life-simplifier, but it's not mandatory...
define([
'lodash'
], function (lodash) {
'use strict';
var Car = function (data) {
lodash.assign(this, data);
};
Car.relations = {};
Car.mixins = {};
lodash.assign(Car.prototype, {
start: function () {
this.engineStarted = true;
},
getSpeed: function () {
return this.speed;
}
});
return Car;
});
Require-topmodel's purpose is to take raw JSON data and inject them into models. Usually, you do that when you just retrieved some data from an API call, but you can inject data from anywhere. Let's take a common example:
I have an API route giving me a car detail.
GET http://mydomain.com/api/cars/1234567
And I have my Car
model, defined just above.
Let's call the API route and inject the model.
Api.get('http://mydomain.com/api/cars/1234567', {model: 'path/to/car'})
.then(function (car) {
car.start();
console.log(car.getSpeed());
});
Some explanation about this code:
Damn ! do I really have to write the entire route path in the Api.get() method ? That's awful! Shame! Shame! Dingdingding!
Okay, okay... how about that ?
var app = angular.module('myApp', ['RestTopModel']);
app.config(['ApiProvider', function (ApiProvider) {
ApiProvider.setApiUrl('http://mydomain.com/api');
}]);
I let you put this base URL in a config file. I won't do all the job for you :)
Maybe you've noticed in the previous example that there were 2 mysterious properties on our Car model.
You can populate these properties to build more complex models, by defining relations between models or adding some behaviours through mixins.
Hint: Mixins are awesome here, because you can define others mixins and relations inside a mixin, simply by populating the same 'mixins' and 'relations' properties on your mixin.
Let's take back our preceding Car model and focus on its relations, at first..
define([
'lodash'
], function (lodash) {
'use strict';
var Car = function (data) {
lodash.assign(this, data);
};
Car.relations = {
Options: 'path/to/option',
Driver: {
key: 'guy',
path: 'path/to/user'
}
};
Car.mixins = {}; // we will see that later...
lodash.assign(Car.prototype, {
getOptions: function () {
return this.Options;
},
getDriver: function () {
return this.Driver;
}
});
return Car;
});
You can define relations in 2 manners. In both cases, the key will be the relation name.
You're smart, and you've already understood that:
Options: 'path/to/option'
and
Options: {
key: 'Options',
path: 'path/to/option'
}
are exactly the same.
So the first one is just a syntactic-sugar if your key needn't to be renamed.
Now we will extend our example with a simple mixin.
define([
'lodash'
], function (lodash) {
'use strict';
var Car = function (data) {
lodash.assign(this, data);
};
Car.relations = {
Options: 'path/to/option',
Driver: {
key: 'guy',
path: 'path/to/user'
}
};
// add some new behaviour to Car prototype
Car.mixins = {
'path/to/batmobile': {}
};
lodash.assign(Car.prototype, {
getOptions: function () {
return this.Options;
},
getDriver: function () {
return this.Driver;
}
});
return Car;
});
Here we linked a mixin to add some new powers to our car. Awesome ! I'm batman !
Okay, but what's a mixin ? How does it look like ?
Here is the mixin (batmobile.js) that powers up your already awesome car.
Don't forget to define it the AMD way, also !
define([], function () {
'use strict';
/**
* Gimme some batpowers !
*/
return function (options) {
this.turboBoost = function (speed) {
// there could be some turbo boost speed limitation amongst countries...
if (options.maxspeed && speed > options.maxspeed) {
speed = options.maxspeed;
}
this.turboBoostEnabled = true;
this.speed = speed;
};
this.fireMissile = function () {
throw new Error("to be implemented...");
};
return this;
};
});
This is a common mixin pattern. Require-topmodel just applies it for our greatest pleasure.
From now, our car can speed up like hell!
// car is a Car instance
car.turboBoost(400);
console.log(car.getSpeed()); // 400 ! OMG ! I pee my pants !
But, hey! What's that speed limitation thing ? And what's that strange empty object {}
you passed as a value when linking the mixin ?
Nice check! You got the point, Charly! There is indeed a way to customize your mixins. Let's look back to our mixin example and add some configuration to it:
// add some new behaviour to Car prototype
Car.mixins = {
'path/to/batmobile': {
maxspeed: 120
}
};
And now, let's try to turboBoost that old car...
// car is a Car instance
car.turboBoost(400);
console.log(car.getSpeed()); // 120. Wat ? Sigh...... f*** switzerland :(
Well, at least I still can fire one or two missiles to relax myself...
// car is a Car instance
car.fireMissile(); // "to be implemented..." Wat ??? Damn !
That's a good opportunity to present a great feature of require-topmodel: nested-whatever.
You can add other mixins or relations inside a mixin. That means you can add a mixin that will add behaviours (new methods) to your object, but that also can define new relations to your object, or even inject others mixins that will add other behaviours or define even more relations to your very object.
Let's take an example and fire some missiles.
First we need a Missile
object, in a missile.js file.
define([
'lodash'
], function (lodash) {
'use strict';
var Missile = function (data) {
lodash.assign(this, data);
};
lodash.assign(Missile.prototype, {
goToTarget: function (gpsCoords) {
// whatever
},
lockOnMovingTarget: function (target) {
// whatever
},
burst: function () {
console.log("BRAAOUM");
}
});
return Missile;
});
Then we can ask our batmobile mixin to add a relation between its host (our Car
instance) and this Missile
object.
There is a few modifications to do... essentially not returning directly an anonymous object.
define([], function () {
'use strict';
/**
* Gimme some batpowers !
*/
var Mixin = function (options) {
this.turboBoost = function (speed) {
// there could be some turbo boost speed limitation amongst countries...
if (options.maxspeed && speed > options.maxspeed) {
speed = options.maxspeed;
}
this.turboBoostEnabled = true;
this.speed = speed;
};
this.getMissiles = function () {
return this.Missiles;
};
this.countMissiles = function () {
return this.Missiles.length;
};
this.fireMissile = function (target) {
var missile;
if (this.countMissiles() === 0) {
throw new Error("No more missile");
}
// return the first element of array and remove it from the array.
missile = lodash.pullAt(this.getMissiles(), 0)[0];
missile.lockOnMovingTarget(target);
return missile;
};
return this;
};
// define relations exactly as you would do in your main object.
Mixin.relations = {
Missiles: {
key: 'missiles',
path: 'path/to/missile'
}
};
return Mixin;
});
Here we are! Our batmobile can fire missiles :) Life just became more sweet.
Hint: require-topmodel will handle itself if your relation is 1-1 or 1-n. If it gets an array, it will therefore conclude that the relation is a 1-n type. In this very missile case, it is obviously a 1-n relation. That's why we named the relation "Missiles" and not "Missile".
There is still a lot to tell about this library, but I don't have time anymore. So just some spoilers here, and you can check the code if something appeals you.
modelkey
configuration to indicate require-topmodel which key it should consider for model injection.There is probably a ton of other things to discover. Just have a look to the code and don't blame me too much :P
FAQs
Model injector
The npm package require-topmodel receives a total of 2 weekly downloads. As such, require-topmodel popularity was classified as not popular.
We found that require-topmodel demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ESLint has added JSON and Markdown linting support with new officially-supported plugins, expanding its versatility beyond JavaScript.
Security News
Members Hub is conducting large-scale campaigns to artificially boost Discord server metrics, undermining community trust and platform integrity.
Security News
NIST has failed to meet its self-imposed deadline of clearing the NVD's backlog by the end of the fiscal year. Meanwhile, CVE's awaiting analysis have increased by 33% since June.