Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Considerations for setting up model relationships with sequelize #94

Closed
DesignByOnyx opened this issue Mar 25, 2016 · 6 comments · Fixed by #159
Closed

Considerations for setting up model relationships with sequelize #94

DesignByOnyx opened this issue Mar 25, 2016 · 6 comments · Fixed by #159
Labels
Milestone

Comments

@DesignByOnyx
Copy link
Contributor

I've talked about this with @daffl and am available to discuss further with anybody who has questions. But the way models and services are generated needs to be altered to allow for models to define relationships and associations with other models. This mostly just affects relational database schemas. Consider the following:

var Auther = sequelize.define('author', {
    name: Sequelize.STRING
});
var Book = sequelize.define('book', {
    title: Sequelize.STRING
});
Author.hasMany(Book);
Book.belongsTo(Author);

The relationship setup at the bottom is the important part. Both models need to be created, and both models need to know about one another. Only at that point can the associations actually be made, and then after it's all done the schemas should be sync()'d with the db.

I have implemented a fix on my current project and am still refining it a little based on my discussion with David earlier. If anybody has any questions, please feel free to ask. Here is the synopsis of what I've done:

Don't call sync() from within a model.
Load all models and save references in a hash table (using sequelize.import())
Iterate over all models. If a static "associate" method exists, call it, passing in the hash table.
Finally call sequelize.sync()

@DesignByOnyx DesignByOnyx changed the title Considerations for setting up model relationships Considerations for setting up model relationships with sequelize Mar 25, 2016
@DesignByOnyx
Copy link
Contributor Author

DesignByOnyx commented Mar 31, 2016

Sequelize recommends the following strategy for setting up associations in an Express app:

http://docs.sequelizejs.com/en/1.7.0/articles/express/#modelsindexjs

I am using this technique locally and it works like a charm. I have refactored all of my models in to a models directory, the index file looks like this:

const model1 = require('./model1');
const model2 = require('./model2');
const user = require('./user');
const Sequelize = require('sequelize');

module.exports = function() {
  const app = this;

  const sequelize = new Sequelize(app.get('db_url'), {
    dialect: 'postgres',
    logging: console.log
  });

  app.set('sequelize', sequelize);

  app.configure(user);
  app.configure(model1);
  app.configure(model2);

  app.set('models', sequelize.models);

  Object.keys(sequelize.models).forEach(function(modelName) {
    if ("associate" in sequelize.models[modelName]) {
      sequelize.models[modelName].associate();
    }
  });

  sequelize.sync();
};

and a model looks like this:

const Sequelize = require('sequelize');

module.exports = function() {
  const app = this;
  const sequelize = app.get('sequelize');

  const Model1 = sequelize.define('Model1', {
    name: {
      type: Sequelize.STRING,
      allowNull: false
    }
  }, {
    freezeTableName: true,
    classMethods: {
      associate () {
        const models = app.get('models');
        Model1.hasMany(models['Model2']);
      }
    }
  });

  return Model1;
};

@marshallswain
Copy link
Member

@DesignByOnyx thanks for doing the research on this and reporting back. I've been meaning to get into this, but this just saved me a load of time. 🕗👍

@ekryski
Copy link
Member

ekryski commented Apr 1, 2016

@DesignByOnyx nice man! That looks pretty great. Definitely awesome for an app where everything is in one. At some point I'll get around to seeing how it mike work with remote services. This might be a pain to change in the generator but at a minimum should probably go into a guide somewhere.

@delta1
Copy link

delta1 commented May 27, 2016

Trying to get my head around doing some model associations in feathers, @DesignByOnyx please help with a few questions if possible:

  • where is MyModel defined?
  • what does ModelHelper do?
  • where is your models/index.js file imported/run in feathers?

@DesignByOnyx
Copy link
Contributor Author

DesignByOnyx commented Jun 10, 2016

Hey @delta1 - sorry I am just getting to this - the email slipped through the cracks.

where is MyModel defined?
That's a typo and I have updated the example above. It should be Model1 (I think this would even work too, so you could to this.hasMany(Model2);)

what does ModelHelper do?
That shouldn't be there either - I copied from my project and didn't delete that line. I have a model helper for sharing some helpful things between my models ;)

where is your models/index.js file imported/run in feathers?
In my app file. This is kind of what it looks like:

// other imports omitted for brevity
const models = require('./models');

const app = feathers();
app.configure(configuration(path.join(__dirname, '..')));

app
  .use(bodyParser.json())
  .use(bodyParser.urlencoded({ extended: true }))
  .configure(rest())
  .configure(socketio())
  .configure(hooks())
  .configure(models)
  .configure(services);

It's also worth noting that services can access and register their corresponding models by doing the following (other service code omitted for brevity):

  const models = app.get('models');

  const options = {
    Model: models.Model1,
    paginate: {
      default: 15,
      max: 50
    }
  };

@delta1
Copy link

delta1 commented Jun 11, 2016

@DesignByOnyx that's awesome, thank you very much

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

Successfully merging a pull request may close this issue.

4 participants