MokoJs / moko

Generator powered models
51 stars 3 forks source link

A few questions #4

Closed paglias closed 10 years ago

paglias commented 10 years ago

I'm having some difficulties in understanding how to exports modules using module.exports.

moko-mongo returns a generator so when using it we have to wrap the model creation inside co(function*(){})(), so how can I export the model as a module?

rschmukler commented 10 years ago

You could do a few things:

Boot.js file that loads the plugins:

var models = [ require('user-model'), require('other-model') ];

co(function*() {
   for(var i = 0; i < models.length; ++i) { yield models[i].use(mongo) }
});

user-model.js

var User = module.exports = moko('User');

User.attr('_id');
...

Or, use the plugin later:

user-model.js

var User = module.exports = moko('User');

User.attr('_id').attr('name');

co(function*() {
 User.use(yield mongo(connectionString))
})()

Or write a boot function for each model, and then call that in a boot.js file. (My preferred approach, I think)

user-model.js

var User = module.exports = moko('User');

User.attr('_id').attr('name');

User._boot = function *() {
   // yield whatever you need
};

boot.js

Models = [User, BlogPost];

var boot = Models.map(function(m) { return m._boot; }).filter(function(m) { return m; ); // filter undefined boot functions

for(var i = 0; i < boot.length; ++i ) {
   yield boot[i]();
}

Note, that with moko-mongo each time you are using yield mongo(connectionString) you are opening a new connection to the database. This is likely not what you want to do. Instead, you should do the following:

var mongo = require('moko-mongo');
co(function*() { 
  var db = yield mongo(connectionString);
  User.use(db);
  Post.use(db);
  AnotherModel.use(db);
})()

This will have all of them share connections.

paglias commented 10 years ago

Thanks. One last thing: any approach I choose, calls to model static methods (like .all()) have to be wrapped inside co? Il 01/giu/2014 21:20 "Ryan Schmukler" notifications@github.com ha scritto:

You could do a few things:

Boot.js file that loads the plugins:

var models = [ require('user-model'), require('other-model') ]; co(function*() { for(var i = 0; i < models.length; ++i) { yield models[i].use(mongo) }});

user-model.js

var User = module.exports = moko('User'); User.attr('_id');...

Or, use the plugin later:

user-model.js

var User = module.exports = moko('User'); User.attr('_id').attr('name'); co(function*() { User.use(yield mongo(connectionString))})()

Or write a boot function for each model, and then call that in a boot.js file. (My preferred approach, I think)

user-model.js

var User = module.exports = moko('User'); User.attr('_id').attr('name'); User._boot = function *() { // yield whatever you need};

boot.js

Models = [User, BlogPost]; var boot = Models.map(function(m) { return m._boot; }).filter(function(m) { return m; ); // filter undefined boot functions for(var i = 0; i < boot.length; ++i ) { yield boot[i]();}

Note, that with moko-mongo each time you are using yield mongo(connectionString) you are opening a new connection to the database. This is likely not what you want to do. Instead, you should do the following:

var mongo = require('moko-mongo');co(function*() { var db = yield mongo(connectionString); User.use(db); Post.use(db); AnotherModel.use(db);})()

This will have all of them share connections.

— Reply to this email directly or view it on GitHub https://github.com/MokoJs/moko/issues/4#issuecomment-44786379.

rschmukler commented 10 years ago

Things that require generators will need to be wrapped in co, but only at the highest point in the call stack.

If you're using something like koa then it's already calling everything inside co and you won't need to wrap anything.

Long story short is that at some point you will need to be executing within co, whether you call it yourself or some other library calls it for you.

paglias commented 10 years ago

@rschmukler thank you! very clear, yes I'm using it with koa

paglias commented 10 years ago

@rschmukler Hi, it looks like I have some problems when yielding moko-mongo multiple times:

I have mongo.js:

var mongo = require('moko-mongo');
var nconf = require('nconf');

module.exports = mongo(nconf.get('MONGODB'));

which I require in every model and .use() in a co wrapped generator:

var mongo = require('../config/mongo');

require('co')(function *(){
  Model.use(yield mongo);
})();

it works fine with one single model but now that I added a second one I get:

/home/matteo/Development/links-koa/node_modules/co/index.js:290
    throw err;
          ^
TypeError: Cannot read property 'collection' of undefined
    at plugin (/home/matteo/Development/links-koa/node_modules/moko-mongo/index.js:14:18)
    at /home/matteo/Development/links-koa/node_modules/moko-mongo/index.js:10:66
    at Moko.BuildMoko.Moko.use (/home/matteo/Development/links-koa/node_modules/moko/lib/builder.js:48:10)
    at /home/matteo/Development/links-koa/src/models/user.js:14:8
    at GeneratorFunctionPrototype.next (native)
    at next (/home/matteo/Development/links-koa/node_modules/co/index.js:83:21)
    at /home/matteo/Development/links-koa/node_modules/co/index.js:102:18
    at processImmediate [as _immediateCallback] (timers.js:374:17)
4 Jun 22:27:40 - [nodemon] app crashed - waiting for file changes before starting...
rschmukler commented 10 years ago

Hmmm, I'm unable to reproduce this error... I was able to yield my mongo connection numerous times as well as use it on multiple collections...

ie:

  before(function*() {
    db = yield mongo('mongodb://localhost:27017/moko-mongo');
    User.use(db);
    BlogPost.use(yield mongo('mongodb://localhost:27017/moko-mongo'));
  });

and

  before(function*() {
    db = yield mongo('mongodb://localhost:27017/moko-mongo');
    User.use(db);
    BlogPost.use(db);
  });

Both worked for me. Any ideas?

paglias commented 10 years ago

Yeah your second example is similar to what I've come up with. Actually the errors happens if I try to yield multiple times the same connection, like: db = mongo(URL); Model1.use(yield mongo); Model2.use(yield mongo);

Sorry for the missing formattation but I'm from phone Il 04/giu/2014 23:36 "Ryan Schmukler" notifications@github.com ha scritto:

Hmmm, I'm unable to reproduce this error... I was able to yield my mongo connection numerous times as well as use it on multiple collections...

ie:

before(function*() { db = yield mongo('mongodb://localhost:27017/moko-mongo'); User.use(db); BlogPost.use(yield mongo('mongodb://localhost:27017/moko-mongo')); });

and

before(function*() { db = yield mongo('mongodb://localhost:27017/moko-mongo'); User.use(db); BlogPost.use(db); });

Both worked for me. Any ideas

— Reply to this email directly or view it on GitHub https://github.com/MokoJs/moko/issues/4#issuecomment-45154995.