Inherit attributes and lifecycle functions of Sails.js models

javascript, node.js, sails.js, waterline

Solution

Using `config/models.js` to provide global defaults for models is perfectly valid. Concerning overriding instance and class methods there is nothing fancy to watch out for according to my tests. Defining a property / method present in `sails.config.models` in a model definition will override it for this model, leaving it undefined won't.

Definitions:

// config/models.js
module.exports.models = {
  attributes: {
    // base model instanceMethod
    toJSON: function() {
      console.log('base.toJSON');
      return this.toObject();
    }
  },

  // base model classMethod
  test: function() {
    console.log('base.test');
  }
};


// api/models/first.js
module.exports = {
  attributes: {

  },

  // Overriding classMethods and lifecycle callbacks
  test: function() {
    console.log('first.test');
  }
};

// api/models/second.js
module.exports = {
  attributes: {
    // Overriding instance methods and attributes
    toJSON: function() {
      console.log('second.toJSON');
      return this.toObject();
    }
  },
}

Tests

> sails.models.first.test();
>'first.test' // sails.config.models.test overridden

> sails.models.first.findOne(1).exec(err,res){ res.toJSON();  });
> 'base.toJSON' // sails.config.models.attributes.toJSON not overridden

> sails.models.second.test();
> 'base.test'; // sails.config.models.test not overridden

> sails.models.second.findOne(1).exec(err,res) { res.toJSON(); });
> 'second.toJSON' // sails.config.models.attributes.toJSON overridden

Problem

I want to create a custom set of attributes and lifecycle methods that are shared between all my Sails.js models. Sails.js automatically creates and registers the model objects by calling the `Waterline.Collection.extend()` method and providing the model definition found inside the `/api/models` directory. What would be the best way to extend my model definition from a parent? I already tried using `_.extend(sails.config.model.parentModel, childModel)` but sadly the `sails` object is not exposed globally (since this is done after loading the orm hook). I could also simply `require()` the base model in all my models and extend it. What would be a clean approach that goes well with Sails?

Original source