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.

Infinite loop when loading fixtures with relationships

See original GitHub issue

I have the following models in my app:

// mirage/models/band.js
import { Model, hasMany } from 'ember-cli-mirage';

export default Model.extend({
  songs: hasMany('song'),
});
// mirage/models/song.js
import { Model, belongsTo } from 'ember-cli-mirage';

export default Model.extend({
  band: belongsTo('band'),
});

And a few fixtures:

// mirage/fixtures/bands.js
export default [
  { id: 1, name: 'Pearl Jam', songIds: [1, 2, 3, 4, 5] },
  { id: 2, name: 'Led Zeppelin', songIds: [6, 7, 8] },
  (...
]
// mirage/fixtures/songs.js
export default [
  { id: 1, title: 'Daughter', rating: 5, bandId: 1 },
  { id: 2, title: 'Yellow Ledbetter', rating: 5, bandId: 1 },
  { id: 3, title: 'Animal', rating: 4, bandId: 1 },
  { id: 4, title: 'Inside Job', rating: 4, bandId: 1 },
  { id: 5, title: 'Who We Are', rating: 2, bandId: 1 },
  (...)
]

When I load these fixtures in my app, they throw it in an infinite loop. I tracked it down to model._setupRelationships.

When the first band (Pearl Jam) is instantiated, it also instantiates (and calls _setupRelationships for) the related songs and each song then seems to instantiate the band again, and then the loop restarts.

I’m not sure if there is a way around this that also makes sure the relationships are correctly set up. If I comment out the band: belongsTo('band') from the song model, no infinite loop is produced but at the same time band.get('songs') is empty.

(I’m using version 0.2.0-beta.4 and the out-of-the-box ActiveModelSerializer for both models)

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:15 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
samselikoffcommented, Feb 24, 2016

Ok, I see what’s going on now.

First, you can see from the console that only the bands are being loaded, and the additional songs aren’t being loaded on the initial request, nor are they being requested by your Ember app. So, there’s two things you could do here. First, you can sideload the songs with the bands on the initial request. To do this, generate a band serializer:

ember g mirage-serializer band

and make it look something like this

import ApplicationSerializer from './application';

export default ApplicationSerializer.extend({

  include: ['songs']

});

This is saying, every time your Mirage mock server serializes a band model, include that band’s related songs. This would get the songs to load on the initial request.

Alternatively, if you want to keep your models asynchronous, you need to provide a links hash with each model. That’s how async works - Ember needs to know where to fetch the related models.

You could do this in your fixtures, something like this:

export default [
  { id: 1, name: 'Pearl Jam', links: {songs: '/bands/1/songs'} },
  { id: 2, name: 'Led Zeppelin' links: {songs: '/bands/2/songs' }},
];

You could also do it in your serializer to save yourself from having to manage ids:

// mirage/serializers/band.js
import ApplicationSerializer from './application';

export default ApplicationSerializer.extend({

  serialize() {
    // This is how to call super, as Mirage borrows [Backbone's implementation of extend](http://backbonejs.org/#Model-extend)
    let json = ApplicationSerializer.prototype.serialize.apply(this, arguments);

    json.links = {
      songs: `/api/bands/${json.id}/songs`
    };

    return json;
  }

});

If you do this, you’ll notice that Ember will make the second request once your template iterates through the band’s songs. The request will fail, since that’s a second route you’ll need to mock in Mirage (i.e. it’s a new endpoint that your actual server must implement). It might look something like this:

// mirage/config.js
this.get('/bands/:id/songs', (schema, request) => {
  let id = request.params.id;
  let band = schema.band.find(id);

  return band.songs;
});

The last thing to be aware of is that your app is using Ember Data’s RESTSerializer but your Mirage mock server is using ActiveModelSerializer. AMS is meant for an AMS-style backend, so you may run into some inconsistencies. If this is just for a demo app, I’d suggest going ahead and setting up your Ember app to use AMS. If there’s going to be an actual server, you should write your mock server in the same format of the real server.


Remember that the point of Mirage is to mock your actual server, so when thinking about async vs sync models, how much to load up front etc., it all depends on the actual app you’re building, and what the production server requirements will be.

Let me know if you need any more help!

0reactions
ballPointPenguincommented, Mar 1, 2016

@balinterdi Yes!!!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Infinite loop when loading fixtures with relationships · Issue #584
When I load these fixtures in my app, they throw it in an infinite loop. I tracked it down to model._setupRelationships . When...
Read more >
Infinite loop while calling a relationship - laravel - Stack Overflow
i think, somewhere in your models, there is infinite recursive calls. Contact model and Service model these two models looks like they calls ......
Read more >
Streamlining tests setup with fixtures in Swift - mokacoding
A fixture method to generate instances with default values in the tests helps ... street: "1 Infinite Loop", town: "Cupertino", state: "CA", ...
Read more >
[Solved]-Rails While Loop: Can't load a page-ruby - appsloveworld
Your code is effectively same as below after first iteration of loop, which is a infinite loop while nil.try(:reify).try(:reason).try(:name).blank?
Read more >
Pytest Plugins to Love - Towards Data Science
For tests which might take a long time or even result in an infinite loop in case of errors, I use pytest-timeout ❤....
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