DB Fabricator 2.0

It hasn’t been that long since I released DB Fabricator version 1.0. But I quickly realized the limitation as I use it more on my project. The biggest annoyance is the fact that when you want to fabricate an object that depends on another fabricated object, you have to fabricate the dependency after resolving the root object promise, resulting in a somewhat verbose nested code like this:

// DB Fabricator 1.0:
Fabricator.fabricate('organization')
.then((org) => {
  Fabricator.fabricate('department', { name: 'IT', organizationId: org.id })
  .then((dept) => {
    Fabricator.fabricate('user', { firstName: 'Bob', departmentId: dept.id });
    Fabricator.fabricate('user', { firstName: 'Jane', departmentId: dept.id });
  })
});

I thought, it would be nice if the fabricated attribute can be a promise, right? That’s a good reason for a major update to version 2.0, because now you can do it this way:

// DB Fabricator 2.0:
let org  = Fabricator.fabricate('organization');
let dept = Fabricator.fabricate('department', { name: 'IT', organizationId: org.then(o => o.id) });
let bob  = Fabricator.fabricate('user', { firstName: 'Bob', departmentId: dept.then(d => d.id)) });
let jane = Fabricator.fabricate('user', { firstName: 'Jane', departmentId: dept.then(d => d.id)) });

This release deserves a major version update because there is a breaking change. In the 1.x version, when you define a template that depends on another fabricator, DB Fabricator assumes that you always want to get the id of the fabricated object.

// DB Fabricator 1.0:
Fabricator.template({
  name: 'department',
  attr: {
    name: 'IT',
    // DB Fabricator 1.0 assumes you want to get the org.id
    organizationId: () => Fabricator.fabricate('organization')
  }
});

Now that attribute can be a promise, you can select which attribute you want to get from the fabricated object. So you have to do it this way:

// DB Fabricator 2.0:
Fabricator.template({
  name: 'department',
  attr: {
    name: 'IT',
    organizationId: () => Fabricator.fabricate('organization').then(o => o.id)
  }
});

Helper Functions

Because of this change, there are a few helper functions that will save you from repeating the same code.

Fabricator.fabGetId fabricates an object and return the id of the fabricated object.

Fabricator.fabricate('organization').then(o => o.id)
// is the same as
Fabricator.fabGetId('organization')

Fabricator.getId returns the .id of a promise

let dept = Fabricator.fabricate('department', { name: 'IT', organizationId: org.then(o => o.id) });
// is the same as
let dept = Fabricator.fabricate('department', { name: 'IT', organizationId: Fabricator.getId(org) });

// if you use Fabricator.getId over and over again, you can alias it so it's shorter
let getId = Fabricator.getId;
let dept1 = Fabricator.fabricate('department', { name: 'IT',      organizationId: getId(org) });
let dept2 = Fabricator.fabricate('department', { name: 'Finance', organizationId: getId(org) });

That’s all the new features on DB Fabricator 2.0. The remaining features from version 1.0 are still the same. I hope this new version makes it even easier to set up database context for your integration test, or other things.

Download the source code at DB Fabricator on Github, or install db-fabricator from npm.