问题描述:

I have a validate function that I am copying into almost every model. I want to abstract it by extending the base bookshelf.Model object. I'm not sure what the correct way to go about this is in ES6. I'd like to do this without forking bookshelf.

An example model:

import bookshelf from '../bookshelf';

import Checkit from 'checkit';

const Design = bookshelf.Model.extend({

tableName: 'foo',

constructor: function() {

bookshelf.Model.apply(this, arguments); // super()

this.on('saving', this.validate.bind(this));

},

validations: {

barColumn: ['required', 'integer', 'greaterThan:0'],

},

validate: function(model, attrs, options) {

let validations;

if (options.patch === true) {

Object.keys(this.validations).forEach((value, index) => {

if (this.attributes[index] !== undefined) {

validations[index] = value;

}

});

} else {

validations = this.validations;

}

return new Checkit(validations).run(this.toJSON());

}

});

export default Design;

The main bookshelf file is here.

网友答案:

I couldn't work out how to extend Bookshelf so I solved it like this:

import bookshelf from '../bookshelf';
import validate from '../utils/validate';

const Design = bookshelf.Model.extend({
  tableName: 'foo',

  constructor: function() {
    bookshelf.Model.apply(this, arguments); // super()
    this.on('saving', validate);
  },

  validations: {
    barColumn: ['required', 'integer', 'greaterThan:0'],
  },
});

export default Design;

And the new validate file:

import Checkit from 'checkit';

export default function validate(model, attributes, options) {
  let validations;
  if (options.patch === true) {
    Object.keys(model.validations).forEach((value, index) => {
      if (attributes[index] !== undefined) {
        validations[index] = value;
      }
    });
  } else {
    validations = model.validations;
  }
  return new Checkit(validations).run(model.toJSON());
};
网友答案:

I think you need Facade or Decorator pattern + some dependency injection.

I used Facade for my own purposes the following way:

class MyFacade {

  constructor(legacyLibrary) {
    this.legacyLibrary = legacyLibrary;
  }

  newMethod() {
    this.legacyLibrary.doSomething();
    this.legacyLibrary.doSomethingElse();
  }

}

export default MyFacade;

Idea of decorator is the same, but you should extend your existing class. So all the functionality will remain the same, but you'll have more methods in it.

The good thing about decorator is that you can nest them. Decorate with one, then with another, etc.

相关阅读:
Top