Factory relationships #28

samselikoff opened this Issue Feb 25, 2015 · 6 comments


None yet

3 participants


No description provided.

@samselikoff samselikoff added the backlog label Feb 25, 2015

I'm assuming from the title that there is no current way to generate relationships between factories?
So the right way to create relationships would be something like:

// tests/factories/contact.js
import Mirage from 'ember-cli-mirage';

export default Mirage.Factory.extend({
  name: 'Pete',
  age: 20,

  friends: function(i) {
    return [
      {id: 100+i, name: "Pete's Friend", age: 21},
      {id: 101+i, name: "Pete's Mom", age: 55},

Or is there a simpler path?


correct, no current way. I've been doing it in my tests:

var contact = create('contact', {friend_ids: [1, 2, 3]});
createList('friend', {contact_id: contact.id});

which is obviously not ideal. But I don't think you'd want to hard-code it like you've done in the factory, since you'll want different relationship setups for different tests. Also those friends won't be inserted into mirage's db.

typically Factory is bare minimum, with traits/relationships used for customizing on a per-test basis


Here's some possibilities for one to one relationships:

// factories/book.js
import Mirage from 'ember-cli-mirage';

export default Mirage.Factory.extend({
  name: 'A Wrinkle in Time',

  author: Mirage.association(),
  author: Mirage.association('factoryName', 'trait1', {some: 'attr'),

  author: Mirage.belongsTo(),
  author: Mirage.belongsTo('factoryName', 'trait1', {some: 'attr'),

  author: function() {
    this.association('factoryName', 'trait1', {some: 'attr'});

  author: ['author', 'factoryName', 'trait1', {some: 'attr'}],

  associations: {
    author: 'author',
    author: ['factoryName', 'trait1', {some: 'attr'}]

  associations: [
    ['author', 'factoryName', 'trait1', {some: 'attr'}]

full api needs to include association(optionalFactory, trait..., overrides...)

@samselikoff samselikoff modified the milestone: 0.1.0 Apr 6, 2015

Were you able to make some progress on this?

This is currently a real pain point for me, as I'm working on a scheduling app that naturally has a lot of many to many and one to many relationships. I'm currently abusing the i parameter really hard.

Here's an example of a automatic many to many relationship:

import Mirage from 'ember-cli-mirage';
import subjects from '../fixtures/subjects';

const LENGTH = subjects.length;

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;

export default Mirage.Factory.extend({
  isVisible: true,
  room: i => `${getRandomInt(1, 2)}.${getRandomInt(0, 2)}${getRandomInt(0, 9)}`,

  studentsLocalOral:     i => getRandomInt(1, 5),
  studentsLocalWritten:  i => getRandomInt(4, 10),
  studentsRemoteOral:    i => getRandomInt(0, 2),
  studentsRemoteWritten: i => getRandomInt(0, 4),

  subject(i) {
    let s = subjects[i % LENGTH];
    s.courses.push(i + 1);
    return s.id;

This is all very hacky, but kinda works. However, this technique has its limits, as I can only "read" data from the fixtures, but not from previously generated factory records. If I had access to the DB in my factories, I could do some more clever stuff. It'd be still ugly as hell, but hey! 😄

Have you yet decided on a proper API for factory relationships? I'd be happy to implement it, if you can't find the time.


Ah, I see that this is probably tracked in #69 for now.


Yep see my note there. Also, I think what you said is good, having an "escape hatch" in a factory to let you access db/schema to do whatever you want.

@samselikoff samselikoff removed the backlog label Oct 30, 2015
@samselikoff samselikoff removed this from the 0.2.0 milestone Oct 30, 2015
@samselikoff samselikoff added the backlog label Jun 4, 2016
@samselikoff samselikoff removed the backlog label Jan 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment