0

Currently, I'm writing an app on Node.js 5.2.0 on a Linux box with Redis and Caminte. When trying to add different prototype methods to a database object, the context of what this refers to constantly shifts within our reference. After calling push in modelRules.js, this shifts types. I was looking for some assistance with:

  1. How to consistently reference the instantiation of a specific module (function that accepts a schema object) outside of the module itself. I want to tack on prototype functions such as addModelBelongsTo to a User object, and sadly my function simply seems to break when referencing the internal modifiable data members within the class.
  2. The proper organization of the prototype accessors. Is there a specific style that should be used when referencing the insides of the instantiations of these classes?
  3. Why the instantiation of the class User persists data across multiple instantiations of the class? For self[restructuredModelName] (type of array), whenever I call this method on one instantiation, another instantiation of the other object already contains the data of the first instantiation. This should not be happening.

User.js

module.exports = function (schema) {
  const IBANVerificationStatusSymbol = Symbol('IBANVerificationStatus');
  const relationalMapper = require('./../relationalMapper');

  const userObj = {
    id: { type: schema.Number },
    firstName: { type: schema.String },
    lastName: { type: schema.String },
    IBAN: { type: schema.String, unique: true },
    IBANVerified: { type: schema.Boolean, default: false },
    IBANVerificationCode: { type: schema.String },
    BIC: { type: schema.String },
    email: { type: schema.String, index: true, unique: true },
    password: { type: schema.String },
    status: { type: schema.Number, default: 0 },
    profilePicture: { type: schema.String },
    phone: { type: schema.String, index: true, unique: true },
    accessToken: { type: schema.String },
    prefix: { type: schema.String, default: '+31' },
    updated: { type: schema.Date, default: Date.now() },
    created: { type: schema.Date, default: Date.now() },
    lastAccessedFeed: { type: schema.Date },
    street: { type: schema.String },
    streetNumber: { type: schema.String },
    postalCode: { type: schema.String },
    city: { type: schema.String },
    country: { type: schema.String },
    FCR: { type: schema.Number, default: 0 },
  };

  // There's GOTTA be a way to typecheck at compilation
  const associationMap = {
    Activity: { belongsTo: 'Activity', hasMany: 'activities' },
    Client: { belongsTo: null, hasMany: 'clients' },
    Group: { belongsTo: 'Group', hasMany: 'groups' },
    Mandate: { belongsTo: null, hasMany: 'mandates' },
    Transaction: { belongsTo: null, hasMany: 'transactions' },
    Update: { belongsTo: null, hasMany: 'updates' },
    Reaction: { belongsTo: null, hasMany: 'reactions' },
  };

  relationalMapper.createRelations(associationMap, userObj, schema);

  const User = schema.define('user', userObj, {

  });

    const setId = function (self, models) {
      //  self.addClients(1);
    };

    User.hooks = {
      afterInitialize: [setId],
    };

    User.prototype.obj = userObj;

    User.associationMap = associationMap;

    User.prototype.associationMap = associationMap;

    return User;
};

modelRules.js:

function addModelBelongsTo(modelName, models, modelObjKey, modelRelated) {
    const restructuredModelName = `memberOf${modelName}`;
    const restructuredModelNameCamel = `addMemberOf${modelName}`;
    const currentModels = models;

    currentModels[modelObjKey].prototype[restructuredModelNameCamel] = function(modelId) {
        const self = this;
        return new Promise((resolve, reject) => {
            if (self[restructuredModelName].indexOf(modelId) <= -1) {
                modelRelated.exists(modelId, function(err, exists) {
                    if (err || !exists) { reject(new Error(err || 'Doesnt exist')); }
                    console.log(`This:${self}\nrestructuredModelName:${JSON.stringify(self[restructuredModelName])}`);
                    self[restructuredModelName].push(modelId);
                    console.log(`This:${self}\nrestructuredModelName:${restructuredModelName}`);
                    self.save((saveErr) => {
                        saveErr ? reject(new Error(saveErr)) : resolve(self);
                    });
                });
            } else {
                reject(new Error(''));
            }
        });
    };
}
Daniel Beck
  • 16,972
  • 5
  • 29
  • 49
  • 7
    Required reading: [How does the “this” keyword work?](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – James Thorpe Apr 07 '16 at 15:00
  • 2
    Rather than use `self`, use the arrow syntax when you want to preserve `this` reference, and use `function() {` when you want `this` to be based on the owner of the caller. (For instance, in your example, `self = this` should be `currentModels[modelObjKey]`.) Note your inclusion of `function(err, exists)` too. – Katana314 Apr 07 '16 at 15:05

0 Answers0