Adapter
Instead of writing ORM-specific code for instancing and persisting created objects, we rely on this interface (and the following default implementation of it). This handles two aspects of factory_botopen in new window: creating an instance of a given model, and then persisting it to the database. (There are other reasons to use it, but that's less important.)
The DefaultAdapter
has barebones implementations of each of the interface's functions to keep code DRY and focused only on the methods that matter. The expectation is that any implementations of Adapter
will be based on DefaultAdapter
.
Example
import {fr, DefaultAdapter} from "fixture-riveter";
export class UserAdapter extends DefaultAdapter {
// This model needs `isNew` set before any fields are set.
build<T>(Model: any): T {
const instance = new Model();
instance.isNew = true;
return instance;
}
}
fr.setAdapter(new UserAdapter(), "user");
2
3
4
5
6
7
8
9
10
11
12
Adapter
methods
None of the methods on an Adapter
will be exposed to the user; they are called internally at various points in the generation of a given fixture. Therefore, the examples below will use the DefaultAdapter
to demonstrate how the methods work.
build()
Called to create an instance of the fixture's Model class. Unless specific arguments are required, DefaultAdapter
's implementation is generally good enough.
export class DefaultAdapter implements Adapter {
// ...
build<T>(Model: any): T {
return new Model();
}
// ...
2
3
4
5
6
Arguments
Argument | Type | Description | Optional? |
---|---|---|---|
Model | Class function | The class function (constructor) | Required |
Return value
Type | Description |
---|---|
Class instance | Instance of Model |
Example
class User {}
const user = adapter.build(User);
user instanceof User
// true
2
3
4
5
save()
Called to persist the instance to the database. Must return the persisted instance, not the parameter instance (if there is a difference). Accepts the class function to allow for static methods on the class to handle persistence (for example, Objection.js).
export class DefaultAdapter implements Adapter {
// ...
async save<T>(instance: any): Promise<T> {
return instance.save();
}
// ...
2
3
4
5
6
Arguments
Argument | Type | Description | Optional? |
---|---|---|---|
instance | Class instance | Instance of Model | Required |
Model | Class function | The class function (constructor) | Optional |
Return value
Type | Description |
---|---|
Class instance | The instance |
Example
class User {}
let user = new User();
user.id
// undefined
user = await adapter.save(user, User);
user.id
// 1
2
3
4
5
6
7
8
destroy()
Called to delete or remove the instance from the database. Must gracefully handle if the instance has not been persisted to the database (for instance, the instance was constructed with fr.build
, not fr.create
). Accepts the class function to allow for static methods on the class to handle deletion (for example, Objection.js).
export class DefaultAdapter implements Adapter {
// ...
async destroy(instance: any): Promise<void> {
await instance.destroy();
}
// ...
2
3
4
5
6
Arguments
Argument | Type | Description | Optional? |
---|---|---|---|
instance | Class instance | Instance of Model | Required |
Model | Class function | The class function (constructor) | Optional |
Return value
Type | Description |
---|---|
Promise | A promise |
Example
class User {}
let user = new User();
await user.save();
await adapter.delete(user, User);
await User.query().findById(user.id);
// []
2
3
4
5
6
7
relate()
Called to "join" two fixture instances together.
WARNING
TODO: clean me up
export class DefaultAdapter implements Adapter {
// ...
async relate(instance: any, name: string, other: any): Promise<any> {
return this.set(instance, name, other);
}
// ...
2
3
4
5
6
Arguments
Argument | Type | Description | Optional? |
---|---|---|---|
instance | Class instance | Instance of a fixture | Required |
name | string | Property on instance to set other to | Required |
other | Class instance | Instance of a fixture | Required |
Model | Class function | The class function (constructor) | Optional |
Return value
Type | Description |
---|---|
Class instance | The instance |
Example
class User {}
class Post {
user: User;
}
const user = new User();
let post = new Post();
post.user
// undefined
post = adapter.relate(post, "user", user);
post.user === user;
// true
2
3
4
5
6
7
8
9
10
11
12
set()
Called to set a property on a fixture instance. Returns the whole instance just in case???
WARNING
TODO: clean me up
export class DefaultAdapter implements Adapter {
// ...
set(instance: any, key: string, value: any): any {
instance[key] = value;
return instance;
}
// ...
2
3
4
5
6
7
Arguments
(instance: any, key: string, value: any)
Argument | Type | Description | Optional? |
---|---|---|---|
instance | Class instance | Instance of a fixture | Required |
key | string | Property on instance | Required |
value | any | A value from an attribute function | Required |
Return value
Type | Description |
---|---|
Class instance | The instance |
Example
class User {}
let user = new User();
user = adapter.set(user, "firstName", "Noah");
user.firstName
// "Noah"
2
3
4
5
6