Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Many to Many relations no longer working #44

Open
dlangerenken opened this issue Feb 9, 2016 · 6 comments
Open

Many to Many relations no longer working #44

dlangerenken opened this issue Feb 9, 2016 · 6 comments

Comments

@dlangerenken
Copy link

After updating all libraries, it seems like the many to many relations are no longer working for me. Do you happen to know if any lib-update might effect barrels?

These are my dependencies:


  "dependencies": {
    "async": "1.5.2",
    "barrels": "1.6.4",
    "bcryptjs": "2.3.0",
    "bluebird": "3.2.2",
    "include-all": "0.1.6",
    "jsonwebtoken": "5.5.4",
    "lodash": "4.3.0",
    "moment-timezone": "0.5.0",
    "passport": "0.3.2",
    "passport-facebook": "2.1.0",
    "passport-github": "1.1.0",
    "passport-google": "0.3.0",
    "passport-local": "1.0.0",
    "passport-twitter": "1.0.4",
    "passport-custom": "1.0.5",
    "rc": "1.1.6",
    "sails": "0.12.0",
    "sails-disk": "0.10.9",
    "sails-hook-apianalytics": "0.3.0",
    "sails-mysql": "0.11.4",
    "sails-fixtures": "1.0.8",
    "ua-parser": "0.3.5",
    "validator": "4.7.1",
    "request": "2.69.0",
    "request-promise": "2.0.0",
    "winston": "^2.1.1",
    "q": "1.4.1"
  }

I populate all models before my 'main'-model is populated. This 'main'-model contains all references to the other models, e.g:

{ "id": 1, "title": "13In est risus, auctor sed,", "clearance": 1, "project": 13, "ipType": 0, "createdUser": 12, "authors": [ 10, 6 ], "published": "1997-01-25", "type": 5, "files": 627, "released": false },

My other json files (such as Project, Clearance, ...) do not contain any information about this 'main' model. I did not need it before the update.

One-To-One relations work fine, one-to-many as well. Only many-to-many don't seem to work anymore.

Do you have any workaround?

@neonexus
Copy link
Contributor

@Dalanie, hopefully this isn't still an issue for you, but I had this problem as well. I can't find the issue, but it seems to be in the Waterline core, as I have issues with .add() manually. The fix, seems to be to use the "through" associations. Minor bugs there too, in that, autoCreatedAt and autoUpdatedAt can not be turned off on the middle-man table... But everything else works as intended otherwise.

@aayush-practo
Copy link

aayush-practo commented Jun 14, 2016

@neonexus @Dalanie I got the same error while writing fixtures for unit test, here are my fixtures, Project and student have many to many association:

Project.json:
[{
   id: 1,
   name: 'abc',
   students: [1]
}]

Student.json: 
[{
  id: 1,
  name: 'xyz',
  projects: [1]
}]

I get the following error:

Details:  [ { type: 'insert',
    collection: 'project_students__student_projects',
    criteria: { student_projects: 1, project_students: 1 },
    values: { student_projects: 1, project_students: 1 },
    err: [Error: Associated Record For student with id = 1 No Longer Exists] } ]

my bootstrap.spec.js is as follows:

var Sails = require('sails'),
  Barrels = require('barrels'),
  sails;

before(function(done) {

  // Increase the Mocha timeout so that Sails has enough time to lift.
  this.timeout(30000);

  Sails.lift({
    // configuration for testing purposes
    log: {
      level: 'error'
    },
     models: {
      connection: 'test',
      migrate: 'drop'
    }
  }, function(err, server) {
    sails = server;
    if (err) return done(err);
    // here you can load fixtures, etc.
     // Load fixtures
    var barrels = new Barrels();

    // Save original objects in `fixtures` variable
    fixtures = barrels.data;
    // Populate the DB
    barrels.populate(['project', 'student'], function(err) {
      if (err){
        return done(err);
      }
      else {
        return done(null, sails)
      }
    }, false);
  });
});

after(function(done) {
  // here you can clear fixtures, etc.
  // console.log('\n');
  Sails.lower(done);
});

What is the possible solution for this, I am using [email protected], [email protected], [email protected]

@neonexus
Copy link
Contributor

@aayush-practo Can I see your models?

@aayush-practo
Copy link

aayush-practo commented Jun 14, 2016

@neonexus, here are the models

Project.js

module.exports = {
  autoPK       : true,
  migrate      : 'safe',
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
     name: {
       type: 'string'
     },
     students: {
       collection: 'student',
       via       : 'projects'
     }
  },

  tableName: 'projects'
}

Student.js

module.exports = {
  autoPK       : true,
  migrate      : 'safe',
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
     name: {
       type: 'string'
     },
     projects: {
       collection: 'project',
       via       : 'students'
     }
  },

  tableName: 'students'
}

@neonexus
Copy link
Contributor

neonexus commented Jun 15, 2016

@aayush-practo, you need to use "through" associations as I mentioned previously. There is a bug down in the Waterline core that needs to be addressed, and this is the way around that.

In other words, add the following model to your set (name it ProjectStudent.js):

module.exports = {
    attributes: {
        // force ID as first column, autoPk in Sails adds it to the end
        id: {
            type: 'int',
            primaryKey: true,
            autoIncrement: true
        },

        project: {
            model: 'project'
        },

        student: {
            model: 'student'
        }
    }
};

Then Project.js:

module.exports = {
  autoPK       : true,
  migrate      : 'safe',
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
     name: {
       type: 'string'
     },
     students: {
       collection: 'student',
       via       : 'project',
       through   : 'projectstudent'
     }
  },

  tableName: 'projects'
}

And Student.js:

module.exports = {
  autoPK       : true,
  migrate      : 'safe',
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
     name: {
       type: 'string'
     },
     projects: {
       collection: 'project',
       via       : 'student',
       through   : 'projectstudent'
     }
  },

  tableName: 'students'
}

@mikedevita
Copy link

mikedevita commented Oct 19, 2016

is this still a bug in waterline and a requirement today? I tried doing as @neonexus suggested, but getting this error Error: Trying to associate a collection attribute to a model that doesn't have a Foreign Key. server is trying to reference a foreign key in servercomponent

models/ServerComponent.js

var ServerComponent = {
  name: 'ServerComponent',
  attributes: {
    id: {
      type: 'int',
      primaryKey: true,
      autoIncrement: true
    },
    server: {
      model: 'server'
    },
    component: {
      model: 'component'
    }
  }
};
module.export = ServerComponent;

models/Server.js

/**
 * Server.js
 *
 * @description :: TODO: You might write a short summary of how this model works and what it represents here.
 * @docs        :: http://sailsjs.org/documentation/concepts/models-and-orm/models
 */

var Server = {
  name: 'Server',
  autoPK: true,
  autoCreatedBy: true,
  attributes: {
    schema: true,
    hostname: {
      type: 'string',
      required: true,
      unique: true
    },

    cpu: {
      type: 'integer',
      required: true
    },

    ram: {
      type: 'float',
      required: true
    },

    swap: {
      type: 'float',
      required: true
    },
    dns: {
      type: 'json'
    },

    sid: {
      type: 'string',
      required: true
    },

    // associations
    roles: {
      collection: 'role',
      via: 'servers'
    },

    component: {
      collection: 'component',
      via: 'server',
      through: 'servercomponent'
    },

    location: {
      model: 'location'
    },
    createdBy: {
      model: 'User'
    },
    updatedBy: {
      model: 'User'
    }
  }
};
module.exports = Server;

models/Component.js

var Component = {
  name: 'Component',
  autoPK: true,
  schema: true,
  autoCreatedBy: true,
  attributes: {
    name: {
      type: 'string',
      required: true,
      unique: true
    },

    // associations
    servers: {
      collection: 'server',
      via: 'component',
      through: 'servercomponent'
    },
    createdBy: {
      model: 'User'
    },
    updatedBy: {
      model: 'User'
    }
  }
};
module.export = Component;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants