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?
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
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
@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
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).
I’ll try this out today. Thanks so much for your help!