Loopback "hasManyThrough" relationship. Where can I add it?

I have a User object and a Hobbie object, both have their models defined in the Loopback and I can see them in the API explorer.

I have a UserHobbie table that links User and Hobbie in relation to ManyToMany. I am trying to declare loopback hasManyThrough like

User.hasMany(Hobbie, {through: UserHobbie});

      

but i cant do it well as it is not showing in explorer . I declared it in /server/server.js

right after the bootstrap section and I tried to do it in /common/User.js

and /common/Hobbie.js

(but in any of them the other model is not visible).

Is there a correct syntax for adding this to User.json or Hobbie.json? This would be my preferred way as everything I entered in the json definition is displayed right in the explorer.

+3


source to share


2 answers


To solve the problem in your JSON model, I will describe the solution below. However, using the hasAndBelongsToMany relationship will solve your problem more easily, and I will describe it below as well.

In your User.json:

  "relations": {
    "Hobbies": {
      "type": "hasMany",
      "model": "Hobbie",
      "through": "UserHobbie",
      "foreignKey": "hobbieId"
    }
  }

      

Inside your Hobbie.json:

  "relations": {
    "Users": {
      "type": "hasMany",
      "model": "User",
      "through": "UserHobbie",
      "foreignKey": "userId"
    }
  }

      

Your UserHobbie.json will look like this (note that you DO NOT define userId OR hobbieId inside "properties":

{
  "name": "UserHobbie",
  "plural": "UserHobbies",
  "base": "PersistedModel",
  "properties": {
    "id": {
      "type": "String",
      "id": true
    }
  },
  "validations": [],
  "relations": {
    "Users": {
        "type": "belongsTo",
        "model": "User",
        "foreignKey": "userId"
    },
    "Hobbies": {
        "type": "belongsTo",
        "model": "Hobbie",
        "foreignKey": "hobbieId"
    }
  },
  "acls": [],
  "methods": []
}

      



THIS IS A SIMPLE WAY FOR THIS BELOW:

DO NOT CREATE the UserHobbies model. Loopback will automatically create a union model for you.

In your user model:

  "relations": {
    "Hobbies": {
      "type": "hasAndBelongsToMany",
      "model": "Hobbie"
    }
  }

      

Hobbie model inside of you:

  "relations": {
    "Users": {
      "type": "hasAndBelongsToMany",
      "model": "User"
    }
  }

      

If you want to do it in code, YOU'RE RIGHT, there are Bootstrap sync issues that prevent this relationship from appearing in explorer. I'll add another answer to show you how.

+9


source


Now, in order for your original linking code implementation to appear in Explorer, here's what you need to do.

First, from the Loopback Projects./server/boot directory, move "explorer.js" to. / server (where server.js is in the project.

The last part. /server/server.js should look something like this (I've cut some of the comments for brevity.

boot(app, __dirname);

... // Removed for brevity

app.use(loopback.urlNotFound());

// The ultimate error handler.
app.use(loopback.errorHandler());

app.start = function() {
  // start the web server
  return app.listen(function() {
    app.emit('started');
    console.log('Web server listening at: %s', app.get('url'));
  });
};

// start the server if `$ node server.js`
if (require.main === module) {
  app.start();
}

      

Now EDIT the last part of the .server / server.js to look like this:



boot(app, __dirname);
    // We took explorer.js out of /boot and put it in /server root next to server.js


var programmaticLoopbackSetup = require('./programmaticLoopbackSetup');
    // If the User has any special Programmatic Loopback Setup (create Model Relationships, etc.) do it first

if (programmaticLoopbackSetup !== undefined) {
    programmaticLoopbackSetup(app, finishUp);
}
else {
    finishUp();  // If you didn't want any Code based Setup
}

// Defer all the rest of the Startup Work until Explorer 
// has all the Model Info it needs from any Async or Programmatic Setup.
function finishUp() {

    require('./explorer')(app);
        // This was formerly done within "boot" above...

        ...  // removed for brevity...

    // Requests that get this far won't be handled
    // by any middleware. Convert them into a 404 error
    // that will be handled later down the chain.
    app.use(loopback.urlNotFound());

    // The ultimate error handler.
    app.use(loopback.errorHandler());

    app.start = function() {
      // start the web server
      return app.listen(function() {
        app.emit('started');
        console.log('Web server listening at: %s', app.get('url'));
      });
    };

    // start the server if `$ node server.js`
    if (require.main === module) {
      app.start();
    }
}

      

Add a new file to. /server/programmaticLoopbackSetup.js and make it look like below (notice how it is called after "loading" and before the application is finished initializing

module.exports = function programmaticLoopbackSetup(app, next) {
    var User = app.models.User;
    var Hobbie = app.models.Hobbie;


    // This Block Below Creates a Many to Many User / Hobbie Relationship directly 

        User.hasAndBelongsToMany(Hobbie);
        Hobbie.hasAndBelongsToMany(User);

    next();  // Callback to finish App Init...
};

      

In this case, you will see the User / Hobbie relationship (using the hasAndBelongsToMany parameter in this case) in the explorer. Make WHATEVER Code LoopBack Model, Datasource or other refinements in LoopbackSetup.js programmer

+3


source







All Articles