Ember-cli-mirage generate data for relationships


#1

I’m having a hard time figuring out how to generate seed data for a relationship. I have a forum model which hasMany posts. Is it possible in my scenario file to generate 5 forums with 10 posts each automatically? Do I need to use fixtures instead?


#2

So you can do it in the scenario and link them manually which is what I used to do, but I recently learned about traits, which are awesome. Here’s an example:

First, in your forum factory:

export default Factory.extend({
  ...
  withTenPosts: trait({
    afterCreate(forum, server) {
      server.createList('post', 10, {...});
    }
  }),
  ...
});

Then in the scenario/test:

server.create('forum', 'withTenPosts', {...});

Neat right?

EDIT: you’ll still need to do the links, if it’s a has many you’d have to add each of the created posts to the forum that’s passed into the trait. Most of the places we do this have a belongsTo instead of a hasMany but it’s the same basic idea. And traits can save a lot of repetition.

EDIT 2: See this part of the mirage docs


#3

Awesome thanks I’ll give it a shot! If it’s not too much trouble could you also post an example of how you used to do it manually? I just started using mirage yesterday so I can use all the help I can get :smiley:


#4

@mrjerome so in our app we have a model hierarchy that goes something like:

instrument ->belongsTo-> product ->belongsTo-> productgroup

So it’s basically an inverted hasMany scenario, where a productgroup has many products and a product has many instruments, but the links go the other way.

Anyway, in my scenario or acceptance tests I’d say something like:

// create productgroup
let productgroup = server.create('productgroup', {...});

// create products
let products = server.createList('product', 5, {..., productgroup, ...});
// or in es5 syntax:
// var products = server.createList('product', 5, {..., productgroup: productgroup, ...});

// create instruments
products.forEach((product) => {
  server.createList('instrument', 10, {..., product, ...});
});

But of course now that I am using traits I can compose all of that into one line where I create the productgroup with a trait, and that trait creates the products with a trait, and that on each product creates the instruments


#5

In your case, if it’s just a forum that hasMany posts, I think it would be even easier. You could make a trait on forum factory like:

export default Factory.extend({
  ...
  withTenPosts: trait({
    afterCreate(forum, server) {
      let posts = server.createList('post', 10, {/* set any attributes you want here */});
      forum.posts = posts;
    }
  }),
  ...
});

Or if you wanted to do it without traits:

let posts = server.createList('post', 10, {/* post overrides here if needed */});
let forum = server.create('forum', {posts});

If your relationship is two way then you’ll have to combine what I was doing above with what you’re doing here (basically set the relationship both ways).


#6

I’ll try this out today. Thanks so much for your help!