question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

hasMany not working with valid models

See original GitHub issue

I have two valid models, Customer and Order, defined in two separate modules.

Example code (omitted columns / options):

var Customer = require('./order');    

var Order = sequelize.define('order', attrs, opts);
Order.belongsTo(Customer, {foreignKey: 'local_customer_id', targetKey: 'id'});
module.exports = Order;

Imagine that Customer is the same, short of the Order.belongsTo(Customer, {foreignKey: 'local_customer_id', targetKey: 'id'}); being replaced with Customer.hasMany(Order, {foreignKey: 'id', targetKey: 'local_customer_id'});, and a require for var Order at the top instead of Customer.

The problem here is, when running the Customer.hasMany line, I get the error ‘hasMany called with something that’s not an instance of Sequelize.Model’. However, if I put both of the lines into the Order module, such as this:

Order.belongsTo(Customer, {foreignKey: 'local_customer_id', targetKey: 'id'});
Customer.hasMany(Order, {foreignKey: 'id', targetKey: 'local_customer_id'});

That works fine, and the relations work.

My question is, why is this happening? The sequelize models work exactly as is, so my definition of them is correct. And they’re both exported via a module.exports = Order-esque line, so they’re both exported correctly.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

8reactions
alitahericommented, Oct 20, 2015

This has nothing to do with sequelize. You can read more about circular dependencies here. In other words, you must first define both Models, export them and THEN require one another and call these associative functions on them to avoid unmet dependencies, something like this:

Order:

// ...
export default sequelize.define('order', {/*...*/});
const Customer = require('./customer');
Order.belongsTo(Customer, {foreignKey: 'local_customer_id', targetKey: 'id'});

Customer:

export default sequelize.define('customer', {/*...*/});
const Order = require('./order');
Customer.hasMany(Order, {foreignKey: 'id', targetKey: 'local_customer_id'});

4reactions
alitahericommented, Oct 20, 2015

What is that export default syntax? Is that ECMA 6?

yeah it is 😁, you can just do module.exports = Order; no difference.

Ahh, I wondered about that asynchronous nature being the culprit.

Actually it’s not asynchronous at all, it’s just that when you require a module node will try to load it, now if you have something like this:

// main.js
require('./a');

// a.js
require('./b').foo; // Expected to be one, but is undefined !!
exports.bar = 1;

// b.js
exports.foo = require('./a').bar;

You would expect that foo should be 1! but it’s not!

let’s reason about what is happening.

  1. the main.js is read by node.
  2. node tries to evaluate a.js
  3. node sees require('./b')
    • at this point the exports object doesn’t have the bar yet! node has not yet “seen” the exports.bar = 1; line
  4. node tries to evaluate b.js
  5. node sees require('./a')
  6. node has a cache for './a'! so it simply returns that not-fully-initialized-cached-version of './a'
  7. node sees .bar
  8. but './a' doesn’t have .bar yet! so it assigns undefined to foo!
  9. evaluation of './b' finishes!
  10. node goes back to './a' to continue execution.
  11. node sees .foo
  12. but .foo was set to undefined in 8! so it also assigns undefined to .bar
  13. NOW node assigns 1 to .bar which is too late (same reason for the error you saw)
  14. evaluation of './a' ends
  15. node goes back to './main'
  16. evaluation of './main' ends
  17. the event-loop is empty the process gets terminated,
  18. unhappy ending 😢

only if in a.js we did this instead:

exports.bar = 1;
require('./b').foo;

We would all go home happy 😄

This is the reason why you see that error. you should understand how imperative programming languages work, and since js is single threaded it’s absolutely imperative.

Read more comments on GitHub >

github_iconTop Results From Across the Web

hasMany Relationship not working?? - Laracasts
Hi, I'm facing a problem with hasMany Relationship So I have 2 tables companies and users A user Belongs to a company (Relationship...
Read more >
Laravel - create on hasmany not working - Stack Overflow
Since you're using relationship to create, i want to see if the $product is a valid model. – Sandeesh. Jun 1, 2017 at...
Read more >
Eloquent hasMany And hasOne Relationship | Learn Laravel
This video will dive into Eloquent's hasMany and hasOne Relationship in Laravel – Learn one of the most popular PHP frameworks for its ......
Read more >
Eloquent: Relationships - The PHP Framework For Web Artisans
Eloquent makes managing and working with these relationships easy, and supports several different types of relationships: One To One; One To Many; Many...
Read more >
Relationships - Ember Data
The naïve solution would be to define models for each nested object and use hasMany and belongsTo to recreate the nested relationship. However,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found