Domanda

in vele.js 0.10 Sto cercando di fare i seguenti

// user.js
module.exports = {
  attributes: {

    uuid: {
        type: 'string',
        primaryKey: true,
        required: true
     } ,
     profile: {

        firstname: 'string',
        lastname: 'string',
        birthdate: 'date',
        required: true
     }
  }
};
.

Sto ricevendo un errore durante il tentativo di creare un utente e Sailsjs non riconoscere l'attributo "Profile".Non sono sicuro se le vele supportano la struttura JSON annidata, e se non sono sicuro di come strutturarlo.

error: Sent 500 ("Server Error") response
error: Error: Unknown rule: firstname
.

Ho provato quanto segue ma è fallito anche

// user.js
module.exports = {
  attributes: {

    uuid: {
        type: 'string',
        primaryKey: true,
        required: true
     } ,
     profile: {

        firstname: {type: 'string'},
        lastname: {type: 'string'},
        birthdate: 'date',
        required: true
     }
  }
};
.

So che c'è un attributo chiamato "JSON" con Sailsjs 0.10, ma non so come questo si adatta a questo modulo.

È stato utile?

Soluzione

Linea di galleggiamento non supporta la definizione di schemi annidati, ma è possibile utilizzare il tipo json per memorizzare oggetti incorporati nel modello.Quindi, lo faresti:

profile: {
    type: 'json',
    required: true
}
.

E poi puoi creare istanze utente come:

User.create({profile: {firstName: 'John', lastName: 'Doe'}})
.

La differenza è che i campi firstName e lastName non saranno convalidati.Se si desidera convalidare che lo schema dell'oggetto profile incorporato corrisponde a quello che desideri, dovrai implementare la callback del ciclo di vita beforeValidate() nella classe del modello:

attributes: {},
beforeValidate: function(values, cb) {
    // If a profile is being saved to the user...
    if (values.profile) {
       // Validate that the values.profile data matches your desired schema,
       // and if not call cb('profile is no good');
       // otherwise call cb();
    }
}
.

Altri suggerimenti

Seguente @ sgress454 Risposta Ho creato qualche logica in più per aiutare con questo problema.

Dal momento che sto usando questo "modelli nidificati" più di una volta, ho creato un servizio con una fabbrica per quelle callback del ciclo di vita di beforeValidade().


Qui come appare:

var _ = sails.util;
var WLValidationError = require('../../node_modules/sails/node_modules/waterline/lib/waterline/error/WLValidationError.js');


function validationError(invalidAttributes, status, message) {
  // Wrapper to helo with validation Errors
  return new WLValidationError({
      invalidAttributes: invalidAttributes,
      status: status,
      message: message
    }
  );
}


function fulfillJSON(attrValues, innerName, innerAttr) {
  // Helper to get default values into the JSON
  // Work with recurrency for arrays
  if (_.isArray(attrValues)) {
    return attrValues.map((attrVal) => {
      return fulfillJSON(attrVal, innerName, innerAttr);
    });
  }

  innerValue = attrValues[innerName];
  // Treat empty values
  if (innerValue == null) {
    // Check to see if it's required
    if (!innerAttr.required) {
      // If not required, try to set the defult value
      innerValue = innerAttr.defaultsTo;
    }
  }

  return attrValues;
}


function validateJSON(attrValues, innerName, innerAttr, invalidAttr, index) {
  // Helper to get error messages if it's not valid
  // Work with recurrency for arrays
  if (_.isArray(attrValues)) {
    invalidAttr = invalidAttr || {};
    _.each(attrValues, (attrVal) => {
      invalidAttr = validateJSON(attrVal, innerName, innerAttr, invalidAttr, attrValues.indexOf(attrVal));
    });
    return invalidAttr;
  }

  invalidMessage = "";

  innerValue = attrValues[innerName];
  // Treat empty values
  if (innerValue == null) {
    // Check to see if it's required
    if (innerAttr.required) {
      invalidMessage += '\n`' + innerName + '` is required!'
    };
  } else
  // Check if it has the right data type
  if (innerAttr.type) {
    if (typeof innerValue !== innerAttr.type) {
      invalidMessage += '\n`' + innerName + '` should be of type `' + innerAttr.type + '`!'
    };
  }

  if (invalidMessage != "") {
    invalidAttr = invalidAttr || {};
    innerInvalid = invalidAttr[innerName];

    if (innerInvalid != null && !_.isArray(innerInvalid)) {
      // Create an array if this attribute already have errors
      innerInvalid = [innerInvalid]
    };
    if (_.isArray(innerInvalid)) {
      // If it's an array, push new errors
      innerInvalid.push({
        index: index,
        field: innerName,
        value: innerValue,
        message: invalidMessage
      });
    } else {
      // If it's the first error, just create the object
      innerInvalid = {
        index: index,
        field: innerName,
        value: innerValue,
        message: invalidMessage
      };
    }

    invalidAttr[innerName] = innerInvalid;
  }
  return invalidAttr;
}


module.exports = {
  validateJSONFactory: function(jsonAttrs) {

    return function(values, cb) {
      // Object to store possible errors
      var invalidAttributes;

      // Go through each attibue trying to find json
      _.each(jsonAttrs, (attrSpecs, attrName) => {
        // Object to store specific attribute errors
        var invalidAttr;

        // Get the values to be validated
        attrValues = values[attrName]
        try {
          attrValues = JSON.parse(attrValues);
        } catch(e) {
          // console.log("Couldn't parse object, ignoring for now!")
          invalidAttributes[attrName] = {
            message: "Couldn't parse object!"
          };
          return false;
        }

        // Check if the specs are those of arrays
        if (_.isArray(attrSpecs)) {
          attrSpecs = attrSpecs[0];
          // Treat should be arrays
          if (!_.isArray(attrValues)) {
            attrValues = [attrValues];
          }
        }

        //Go through the specs in order to do some validation
        _.each(attrSpecs, (innerAttr, innerName) => {
          attrValues = fulfillJSON(attrValues, innerName, innerAttr);
          invalidAttr = validateJSON(attrValues, innerName, innerAttr, invalidAttr);
        });

        // Overload initial value, give back as string, the same way we got it!
        // values[attrName] = JSON.stringify(attrValues)
        values[attrName] = attrValues;

        // Make errors available outside
        if (invalidAttr != null){
          invalidAttributes = invalidAttributes || {};
          invalidAttributes[attrName] = invalidAttr;
        }

      }) // </each>

      if (invalidAttributes != null) {
        return cb(validationError(invalidAttributes));
      }

      return cb();

    } // </return function>
  } // </fulfillJSONFactory>
}  // </module.exports>
.


E, nel modello, ho questo:

const jsonAttrs = {
  profile: {
    // Here you can add some specifications for your nested attributes
    // If you wish, you can have a list of profiles by wrapping this inner object in an array
    firstName: {
      type: 'string',  // `type` will be used in a `typeOf` comparison
      required: true  // `required` will check if the value is present
      // defaultsTo: 'John'  -  is also an option and will bring this value if none is given
      // more options can be added here, you just need to implement some logic on the service
    },
    lastName: {
      type: 'string',
      required: true
    }
  }
}


module.exports = {

  attributes: ModelService.complete({
    profile: {
      // Note that you don't need anything in here
    }
  }),

  beforeValidate: ModelService.validateJSONFactory(jsonAttrs)

};
.


So che non è ancora perfetto, forse dovrei renderlo un gancio, ma sono ancora confuso sul modo migliore per farlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top