Replies: 3 comments 1 reply
-
|
Hey, @mdbiscan. Thanks for proposing this. The seeding functionality has long been on my todo list, and I even gave it some attempts in #33 in the past. TLDR I agree, it's not easy due to the relationships and the safe amount of implicit behaviors one would expect when seeding their models. I will keep your utilities and the proposed API in mind when I come back to this discussion. For now, it's not on my radar. |
Beta Was this translation helpful? Give feedback.
-
|
I'm posting my seed file here to show a real world example on how I'm using it. const db = require('./factories');
const columns = require('./columns');
const elements = require('./elements');
const fixtures = require('./fixtures');
const Seed = require('./seed');
const { faker } = require('@faker-js/faker');
const { transactionPrice } = require('../utils/calculate');
// Seeding with predetermined values
faker.seed(123);
// Seeds
const seed = new Seed(db);
Object.keys(columns).forEach(Name => {
seed.one('Column', {
Name,
All: columns[Name].All,
Selected: columns[Name].Selected,
});
});
elements.Permissions.forEach(Permission => seed.one('Permission', Permission));
elements.PlatformTypes.forEach(PlatformType =>
seed.one('PlatformType', PlatformType)
);
elements.Bases.forEach(Base => seed.one('UnderlyingBase', Base));
elements.Quotes.forEach(Quote => seed.one('UnderlyingQuote', Quote));
const USA = fixtures.Countries.find(Country => Country.Code === 'US');
const Canada = fixtures.Countries.find(Country => Country.Code === 'CA');
elements.Products.forEach(({ Description, Live, Symbol, Underlying }) => {
const Base = db.UnderlyingBase.findFirst({
where: {
Symbol: {
equals: Underlying.Base,
},
},
});
const Quote = db.UnderlyingQuote.findFirst({
where: {
Symbol: {
equals: Underlying.Quote,
},
},
});
seed.one('Product', {
Base,
Description,
Live,
Quote,
Symbol,
});
});
const SuperOperator = seed.one('ComplianceOperator', {
Name: 'Super Operator',
});
seed.many('ComplianceOperator', 10);
const SuperGroup = seed.one('Group', {
Name: 'Super Group',
Permissions: db.Permission.getAll(),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: SuperOperator,
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
});
const DevsGroup = seed.one('Group', {
Name: 'Devs',
Permissions: db.Permission.getAll(),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: SuperOperator,
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
Parent: SuperGroup,
});
const AccountingGroup = seed.one('Group', {
Name: 'Accounting',
Permissions: db.Permission.getAll().filter(({ Key }) =>
Key.includes('accounting')
),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: SuperOperator,
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
Parent: SuperGroup,
});
const ReadOnlyGroup = seed.one('Group', {
Name: 'ReadOnly',
Permissions: db.Permission.getAll().filter(({ Key }) => Key.includes('view')),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: seed.one('ComplianceOperator'),
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
Parent: SuperGroup,
});
const SuperPhoneNumbers = seed.many('PhoneNumber', 1, { Phone: '312444555' });
seed.one('Account', {
Email: 'super@user.com',
FirstName: 'Super',
LastName: 'User',
FullName: 'User, Super',
Employer: 'DigitalMint',
PhoneNumbers: SuperPhoneNumbers,
PreferredPhoneNumber: SuperPhoneNumbers[0],
Addresses: seed.many('Address', 1),
ApprovalTier: 3,
Status: 12,
ComplianceOperator: SuperOperator,
OperatingCountry: USA,
Groups: [DevsGroup, AccountingGroup, SuperGroup],
});
const ReadOnlyPhoneNumbers = seed.many('PhoneNumber', 1, {
Phone: '773444555',
});
seed.one('Account', {
Email: 'read@only.com',
FirstName: 'Read',
LastName: 'Only',
FullName: 'Only, Read',
Employer: 'DigitalMint',
PhoneNumbers: ReadOnlyPhoneNumbers,
PreferredPhoneNumber: ReadOnlyPhoneNumbers[0],
Addresses: seed.many('Address', 1),
ApprovalTier: 1,
Status: 10,
ComplianceOperator: SuperOperator,
OperatingCountry: USA,
Groups: [ReadOnlyGroup],
});
const Accounts = [];
seed.collect(154, Accounts, () => {
// Customer Tier 1
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
AccountTier: 1,
Status: 1,
};
});
seed.collect(36, Accounts, () => {
// Customer Tier 2
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
AccountTier: 2,
Status: 2,
};
});
seed.collect(19, Accounts, () => {
// Customer Tier 3
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
AccountTier: 3,
Status: 3,
};
});
seed.collect(21, Accounts, () => {
// Banned
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
ApprovalTier: 0,
Status: 11,
Banned: true,
};
});
seed.collect(43, Accounts, () => {
// Employees
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
Employer: 'DigitalMint',
ApprovalTier: 3,
Status: 12,
Banned: true,
Groups: [DevsGroup],
};
});
seed.collect(14, Accounts, () => {
// Accounting
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
Employer: 'DigitalMint',
ApprovalTier: 3,
Status: 3,
Groups: [AccountingGroup],
};
});
seed.collect(22, Accounts, () => {
// Service
return {
Addresses: seed.many('Address', 1),
PhoneNumbers: seed.many('PhoneNumber', 1),
ApprovalTier: 0,
Status: 10,
Banned: true,
Groups: [ReadOnlyGroup],
};
});
seed.shuffle('Account', Accounts, ({ PhoneNumbers, LastName, FirstName }) => {
return {
PreferredPhoneNumber: PhoneNumbers[0],
FullName: `${LastName}, ${FirstName}`,
};
});
seed.one('Profile', {
FirstName: 'Super',
LastName: 'User',
PhoneNumber: '7734445555',
PIN: '1234',
Address: () => seed.one('Address'),
});
seed.many('Profile', 10, {
Address: () => seed.one('Address'),
});
seed.many('Address', 3, { Active: false });
const LocationGroup = seed.one('Group', {
Name: 'Locations',
Permissions: db.Permission.getAll().filter(({ Key }) => Key.includes('view')),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: faker.helpers.arrayElement(
db.ComplianceOperator.getAll()
),
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
});
const LocationCreate = (fields = {}) => {
const Group = seed.one('Group', {
Permissions: db.Permission.getAll().filter(({ Key }) =>
Key.includes('view')
),
PhoneNumber: seed.one('PhoneNumber'),
Address: seed.one('Address'),
ComplianceOperator: faker.helpers.arrayElement(
db.ComplianceOperator.getAll()
),
GroupCommissions: seed.many('GroupCommission', 1),
CommissionEmails: seed.many('CommissionEmail', 1),
ACHEmails: seed.many('ACHEmail', 1),
Parent: LocationGroup,
});
const PlatformType = faker.helpers.arrayElement(db.PlatformType.getAll());
return {
Address: seed.one('Address'),
CreditAccount: seed.one('CreditAccount'),
ComplianceOperator: seed.one('ComplianceOperator'),
DebitAccount: seed.one('DebitAccount'),
CashCourier: seed.one('CashCourier'),
PlatformTypes: [PlatformType],
PlatformType: PlatformType.Name,
Group,
CashOperatingGroup: Group,
...fields,
};
};
const Locations = [];
seed.collect(87, Locations, LocationCreate);
seed.collect(32, Locations, () =>
// Inactive
LocationCreate({
Active: false,
})
);
seed.collect(29, Locations, () =>
// Decommissioned
LocationCreate({
Active: false,
Decommissioned: true,
})
);
seed.shuffle('Location', Locations);
seed.many('Platform', 140, {
Group: () => faker.helpers.arrayElement(db.Group.getAll()),
PlatformType: () => faker.helpers.arrayElement(db.PlatformType.getAll()),
Location: () =>
faker.helpers.arrayElement(
db.Location.getAll().filter(({ Decommissioned }) => !Decommissioned)
),
});
const TransactionAccounts = db.Account.findMany({
where: {
Status: {
between: [1, 3],
},
},
});
const Transactions = seed.many(
'Transaction',
261,
{
ComplianceOperator: () =>
faker.helpers.arrayElement(db.ComplianceOperator.getAll()),
Group: () => faker.helpers.arrayElement(db.Group.getAll()),
},
() => {
const Account = faker.helpers.arrayElement(TransactionAccounts);
const Event = faker.helpers.arrayElement(elements.Events);
const Platform = faker.helpers.arrayElement(db.Platform.getAll());
const State = faker.helpers.arrayElement(elements.States);
const Product = db.Product.findFirst({
where: {
Symbol: {
equals: Platform.Products,
},
},
});
const Price = transactionPrice(State.StateDesc === 'Settled');
return {
Account,
Base: Product.Base,
Location: Platform.Location,
Platform,
Product,
Quote: Product.Quote,
...Price,
...Event,
...State,
};
}
); |
Beta Was this translation helpful? Give feedback.
-
|
With the recent release of 1.0, could you please let me know if seeding works/is possible the way you expect? I'd like to explore this in more detail. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm using this package not in msw, but other mocking environments. I love it, but its missing a few pieces that I think would be really helpful, such as seeding and
afterCreatemethods for updating fields after model creation that are dependent on others.Seeding
One in particular is easy seeding methods. I came from using Mirage for years, and I loved the ability to create lists on the fly, but the hard part can be the associations. I built out a little class for myself to be able to seed quickly.
Only other thing missing is a method after fields are written to update programmatically. I wrote up something here #272
EDIT: Updated the class with some new functions
Examples:
Db objects get returned in the order of creation, but I found sometimes randomized data with faker isn't enough to make the data feel real. For example, I might need a small percentage of inactive accounts vs a larger percentage of active accounts to look and feel more realistic in my system. Since the db returns objects the order of creation, it would look funny to see all the inactive accounts at the end of a list.
After Create
EDIT - I closed #273 for now, since it's discussed in here with seeding.
Beta Was this translation helpful? Give feedback.
All reactions