How can I add an instance method to all Models in sails.js?

半世苍凉 提交于 2019-12-10 02:04:38

问题


I'd like to add a default toDisplay function to all models which will use metadata, not unlike attribute/association definitions, to perform manipulations on the instance's attributes/associations making them suitable for display in the UI.

for example:

Foo.findOne(someId)
  .exec(function(err, foo) {
    ...
    res.view({
      foo: foo.toDisplay(),
    });
  });

So, I'd like to add this function too all models. I can imagine a

Model.prototype.toDisplay = ... 

solution, but I'm not sure where to get Model from (some long require('waterline/..../model') path?), and if I had Model, where to put that snip-it.

Please advise.


回答1:


Model configuration is fully documented here on SailsJS.org. @umassthrower is correct in pointing out that adding an instance method to config/models.js would add it to all of your models; he's also correct in observing that this is not the intended use of the config file.

The reason you're finding this a bit more challenging in Sails than Rails is that Ruby has real classes and inheritance, and Javascript just has objects. One fairly clean way to simulate inheritance and extend your model objects from a "base" object would be to use something like Lodash's _.merge function. For example you could save your base model in lib/BaseModel.js:

// lib/BaseModel.js
module.exports = {

  attributes: {

    someAttribute: 'string',

    someInstanceFunction: function() {
      // do some amazing (synchronous) calculation here
    }

  }

};

Then in your model file, require lodash and use _.extend:

// api/models/MyModel.js
var _ = require('lodash');
var BaseModel = require("../../lib/BaseModel.js");
module.exports = _.merge({}, BaseModel, {

  attributes: {

    someOtherAttribute: 'integer'

  }

};

The attributes from your base model will be merged with MyModel, with MyModel taking precedence.

Setting the first argument to the empty model {} is important here; _.merge is destructive for the first object sent in, so if you just did _.merge(BaseModel, {...} then the base model would be modified.

Also, remember to npm install lodash!




回答2:


This can be done by adding your function to your model attributes, like so:

module.exports = {
    attributes: {
        attribute1: {
            type: String
        },
        attribute2: {
            type: String
        },
        toDisplay: function () {
            // your function here
        }

        // You can also override model functions like .toJSON or .toObject
        toJSON: function () {
            // your custom JSON here
        }
    }
}

There's more information in the Sails documentation for models, under Attribute Methods. It's worth it to note that depending on what you're doing, you may not need a toDisplay() method at all; you could just override the toJSON() method if you're only trying to format any output or remove any sensitive information.



来源:https://stackoverflow.com/questions/27538630/how-can-i-add-an-instance-method-to-all-models-in-sails-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!