Samuel Bolduc
Samuel Bolduc

Reputation: 19173

Chaining models relations in node.js (node-orm) like in Rails

I'm building a relatively big NodeJS application, and I'm currently trying to figure out how to fetch the data I need from the DB. Here is a part of my models :

One user has one role, which has access to many modules (where there's a table role_modules to link roles and modules).

In Rails, I would do something like user.role.modules to retrieve the list of the modules he has access to. In NodeJS it's a bit more complicated. I'm using node-orm2 along with PostgreSQL. Here is what I have so far:

req.models.user.find({email: req.body.user}, function(err, user) {
  user[0].getRole(function(err, role) {
    role.getModules(function(err, modules) {
      var list_modules = Array();
      modules.forEach(function(item) {
        console.log(item);
        list_modules.push(item.name);
      })

But I can't do this, because item only contains role_id and module_id. If I want to have the name, I would have to do item.getModule(function() {...}), but the results would be asynchronous ... so I don't really see how I could end up with an array containing the names of the modules a user has access to ... have any idea?

Also, isn't that much slower than actually running a single SQL query with many JOIN? Because as I see it, the ORM makes multiple queries to get the data I want here...

Thank you!

Upvotes: 2

Views: 1413

Answers (1)

tgriesser
tgriesser

Reputation: 2808

I wrote an ORM called bookshelf.js that aims to simplify associations and eager loading relations between models in SQL. This is what your query would probably look like to load the role & modules on a user given your description:

var Module = Bookshelf.Model.extend({
  tableName: 'modules'
});

var Role = Bookshelf.Model.extend({
  tableName: 'roles',

  modules: function() {
    return this.belongsToMany(Module);
  }
});

var User = Bookshelf.Model.extend({
  tableName: 'users'

  role: function() {
    return this.hasOne(Role);
  }
});


User.forge({email: req.body.user})
  .fetch({
    require: true,
    withRelated: ['role.modules']
  })
  .then(function(user) {

    // user, now has the role and associated modules eager loaded
    console.log(user.related('role'));
    console.log(user.related('role').related('modules'))

  }, function(err) {

    // gets here if no user was found.

  });

Might be worth taking a look at.

Upvotes: 2

Related Questions