从不在 class 中的对象中删除属性

Delete properties from object that are not in a class

我正在使用 adonisjs,并试图清理服务器上的 post 请求。我取回的数据具有未映射到 table/model 的额外属性,因此在我尝试保存时出错。这是更新方法

async update ({ params, request, response }) {
  const contract = await Contract.find(params.id);
  contract.merge(request.post());
  return await contract.save();
}

问题是,当我早些时候根据 get 请求返回合同时,我添加了一些计算属性。我可以按照

的方式做一些事情
const { prop1, prop2 } = request.post();

但这感觉不像是面向未来的或干净的解决方案。理想情况下,我希望该对象仅具有在 table/model 上定义的属性。我有一个验证器设置,如 the validator docs 中所述,但它仍然允许其他属性绕过它。

帮手怎么样class?

class RequestContractExtractor{
  static desiredProps = [
    "prop1",
    "prop2",
  ]; // you could replace this with a list you get from your model class

  constructor(requestData){
    desiredProps.forEach(prop => this[prop] = requestData[prop]);
  }

  static from(...args){ return new this(...args); }
}

那么你可以这样做:

async update ({ params, request, response }) {
  const contract = await Contract.find(params.id);
  contract.merge(RequestContractExtractor.from(request.post()));
  return await contract.save();
}

我通过在模型中添加 beforeSave 挂钩解决了这个问题 class 该过滤器在对象上的属性,这允许我们保留一个瘦控制器。

const FIELDS = ['id', 'description'];

class Contract extends Model {
  static boot() {
    super.boot();
    this.addHook('beforeSave', async contractInstance => {
      Object.keys(contractInstance.$attributes).forEach(key => {
        if (!CONTRACT_FIELDS.includes(key)) {
          delete contractInstance.$attribute[key];
        }
      });
    });
  }
}

我通过在对象上添加过滤器属性的 beforeSave 挂钩解决了这个问题。

/app/Model/Hooks/ContractHook.js

创建一个文件
'use strict'

const ContractHook = module.exports = {}

const CONTRACT_FIELDS = ["id", "description"];
ContractHook.removeDynamicFields = async (contractInstance) => {
  if (contractInstance) {
    Object.keys(contractInstance.$attributes).forEach((key) => {
      if (!CONTRACT_FIELDS.includes(key) && contractInstance.$attributes[key]) {
        delete contractInstance.$attributes[key];
      }
    });
  }
};

像这样在你的模型中使用它...

class Contract extends Model {
  static boot() {
    super.boot();

    this.addHook("beforeCreate", [
      "ContractHook.removeDynamicFields",
    ]);
  }