Loading Models in Patio
One question that I often get is how to work with models in patio
. Models in patio
are different in that they are not synchronous in the loading of them. The reason is because we load the schema when you define the model object.
The reason we did this when designing patio
was that it allows for a clean seperation of database DDL. You may ask what difference does it make, well…
This can come in handy when you have multiple pieces of software reading from a single database.
Imagine you have a ruby implementation of your model and a javascript implementation, for whatever reason (maybe your migrating from ruby to javascript and you cannot do it all at once). Well if this is the case then with patio you can just add your models and not have to worry about schema design as patio will dynamically load it at run time.
This allows the javascript developers to focus on gettings things done rather than setting up their models to match the ruby schemas field for field!
Getting started
When I work with patio I typically follow the same basic directory structure
- lib
- models
- Model1.js
- Model2.js
- Model3.js
- index.js
Then in index.js I have a method like the following
(function(){
"use strict";
var path = require("path"),
comb = require("comb"),
patio = require("patio");
var CONNECT_URI = "mysql://test:testpass@localhost:3306/db?minConnections=1&maxConnections=5";
patio.connect(CONNECT_URI);
//add patio as an export so I dont have any
//module issues where I have the wrong instance of patio.
exports.patio = patio;
exports.load = (function(){
//create a shared promise so we only load the models once, and a loaded var to store if
//we have called load before
var loadPromise = new comb.Promise(), loaded = false;
return function(cb){
if(!loaded){
//we havent loaded yet so load the models directory at once then call the loadPromise
patio.import(path.resolve(__dirname, "./models")).then(loadPromise);
loaded = true;
}
if(cb){
//classic accepts a callback like a normal node callback i.e. function(err, result){};
loadPromise.classic(cb);
}
//return the promise incase you want to use the promise api
return loadPromise;
};
})();
})();
I usually have my model in its own module so I can use it accross services we’ll call our model package my-model
So in other modules I add it as a dependency and use it like so
(function(){
"use strict";
var models = require("my-model"),
patio = models.patio;
models.load(function(err){
if(err){
console.error(err.stack);
process.exit();
}else{
var Model1 = patio.getModel("model1"),
Model2 = patio.getModel("model2");
//do some thing with them
}
});
})();
Inter-model Dependencies
Sometimes you have models that are dependent among eachother to get around this the model has a patio
property or you can just require patio
. Then in the constructor of the model you can set up your dependencies.
So if Model2 needed Model1 for a query you can do the following
(function(){
"use strict";
var patio = require("patio"),
Model1;
patio.addModel("model2", {
instance : {
constructor : function(){
if(!Model1){
//now you can use it
Model1 = patio.getModel("model1");
}
}
},
static : {
someQueryMethod : function(){
//using the patio property
var Model1 = this.patio.getModel("model1");
//do something with it
}
}
});
});
Wrapup
Hopefully this boiler plate can help you get started with patio
and the model loading pattern.
I have set up a repo at https://github.com/doug-martin/patio-boilerplate
Hi Douglas,
ReplyDeleteI would like to try your patio orm. But it does not compile on windows. I used npm install patio. Do you have any fixes for this to work with Windows 7. You help would be greatly appreciated.
Regards
N.K.Rajan