Last active
November 4, 2017 20:53
-
-
Save hetsch/23b36e1ad01b46dcf2226e327667f3a6 to your computer and use it in GitHub Desktop.
Revisions
-
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,7 @@ function initDatabase() { const knex = Knex({ dialect: 'sqlite3', connection: { filename: './test.db' // ':memory:' }, useNullAsDefault: true, debug: false @@ -73,12 +73,12 @@ class BaseModel extends objection.Model { } castBooleanFields(json) { const jsonSchema = this.constructor.jsonSchema.properties; // const booleanFields = Object.keys(json).filter(key => schema.hasOwnProperty(key) && schema[key].type === "boolean"); Object.entries(json).forEach(([key, value]) => { if ( Object.prototype.hasOwnProperty.call(jsonSchema, key) && jsonSchema[key].type === 'boolean' ) { json[key] = Boolean(value); } @@ -335,6 +335,7 @@ function* fixtures(knex) { slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ // See: https://github.com/Vincit/objection.js/issues/480 /* OLD RELATION: This is the ProductAttribute that was created in the fixtures */ { isOptional: true, -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 2 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -31,8 +31,7 @@ class BaseModel extends objection.Model { } static find(id) { let query = this.query().findById(parseInt(id, 10)); if (this.relations.length > 0) { query = query.eager(this.relations); } @@ -368,7 +367,7 @@ function* fixtures(knex) { // const productClass = await ProductClass.find(1); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log(productClass.productAttributes[0]); console.log('\nAFTER UPDATE\n'); -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 11 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -32,8 +32,7 @@ class BaseModel extends objection.Model { static find(id) { let query = this.query() .findById(parseInt(id, 10); if (this.relations.length > 0) { query = query.eager(this.relations); } @@ -77,11 +76,14 @@ class BaseModel extends objection.Model { castBooleanFields(json) { const schema = this.constructor.jsonSchema.properties; // const booleanFields = Object.keys(json).filter(key => schema.hasOwnProperty(key) && schema[key].type === "boolean"); Object.entries(json).forEach(([key, value]) => { if ( Object.prototype.hasOwnProperty.call(schema, key) && schema[key].type === 'boolean' ) { json[key] = Boolean(value); } }); return json; } @@ -337,13 +339,13 @@ function* fixtures(knex) { /* OLD RELATION: This is the ProductAttribute that was created in the fixtures */ { isOptional: true, id: 1 // this is the pk of the related ProductAttribute? }, /* NEW RELATION: This should relate the current ProductClass with an EXISTING ProductAttribute with ProductAttribute::id = 2 */ { isOptional: false, id: 2 // this is the pk of the related ProductAttribute? }, /* NEW RELATION: Should create a NEW ProductAtribute and realte it to the current ProductClass */ { @@ -357,7 +359,7 @@ function* fixtures(knex) { /* OLD RELATION: This is the ProductAttribute that was created in the fixtures */ { isOptional: false, id: 2 // this is the pk of the related ProductAttribute? } ] }); @@ -366,6 +368,7 @@ function* fixtures(knex) { // const productClass = await ProductClass.find(1); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log(productClass.productAttributes[0]) console.log('\nAFTER UPDATE\n'); -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 0 additions and 160 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,160 +0,0 @@ -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 8 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -40,9 +40,15 @@ class BaseModel extends objection.Model { return query; } static create(data, upsertGraphOptions) { return objection.transaction(this.knex(), trx => { return this.query(trx).insertGraph( data, upsertGraphOptions || { relate: true, unrelate: true } ); }); } -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 29 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -46,11 +46,17 @@ class BaseModel extends objection.Model { }); } static update(data, upsertGraphOptions) { return objection.transaction(this.knex(), trx => { return this.query(trx) .where('id', data.id) .upsertGraph( data, upsertGraphOptions || { relate: true, unrelate: true } ); }); } @@ -289,10 +295,26 @@ function* fixtures(knex) { const dumpData = Promise.coroutine(function* dump() { const line = '\n\n*****************\n%s:\n\n%s\n*****************\n\n'; console.info( line, 'ProductClasses', util.inspect(yield ProductClass.all()) ); console.info( line, 'ProductAttributes', util.inspect(yield ProductAttribute.all()) ); console.info( line, 'ProductClass_ProductAttribute', util.inspect(yield knex.select().from('ProductClass_ProductAttribute')) ); console.info( line, 'ProductClass_VariantAttribute', util.inspect(yield knex.select().from('ProductClass_VariantAttribute')) ); // yield Promise.resolve(); }); @@ -336,6 +358,7 @@ function* fixtures(knex) { console.log('\nUPDATED PRODUCT CLASS\n'); // const productClass = await ProductClass.find(1); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log('\nAFTER UPDATE\n'); -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -336,7 +336,6 @@ function* fixtures(knex) { console.log('\nUPDATED PRODUCT CLASS\n'); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log('\nAFTER UPDATE\n'); -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -41,21 +41,21 @@ class BaseModel extends objection.Model { } static create(data) { return objection.transaction(this.knex(), trx => { return this.query(trx).insertGraph(data); }); } static update(data) { return objection.transaction(this.knex(), trx => { return this.query(trx) .where('id', data.id) .upsertGraph(data); }); } static delete(id) { return objection.transaction(this.knex(), trx => { return this.query(trx) .where('id', parseInt(id, 10)) .delete(); @@ -300,7 +300,7 @@ function* fixtures(knex) { await dumpData(); const productClass = await ProductClass.update({ id: 1, name: 'productclass_name_1', slug: 'productclass_slug_1', @@ -311,8 +311,8 @@ function* fixtures(knex) { isOptional: true, '#dbRef': 1 }, /* NEW RELATION: This should relate the current ProductClass with an EXISTING ProductAttribute with ProductAttribute::id = 2 */ { isOptional: false, '#dbRef': 2 @@ -336,7 +336,7 @@ function* fixtures(knex) { console.log('\nUPDATED PRODUCT CLASS\n'); // const productClass = await ProductClass.find(1); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log('\nAFTER UPDATE\n'); -
hetsch revised this gist
Nov 4, 2017 . No changes.There are no files selected for viewing
-
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 160 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,160 @@ INITIAL DATABASE STATE ***************** ProductClasses: [ ProductClass { id: 1, name: 'productclass_name_1', slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ [Object] ], variantAttributes: [ [Object] ] } ] ***************** ***************** ProductAttributes: [ ProductAttribute { id: 1, name: 'attribute_name_1', slug: 'attribute_slug_1', isOptional: false, dataType: 'string' }, ProductAttribute { id: 2, name: 'attribute_name_2', slug: 'attribute_slug_2', isOptional: false, dataType: 'number' } ] ***************** ***************** ProductClass_ProductAttribute: [ { id: 1, productClassId: 1, productAttributeId: 1, isOptional: 1, order: 1 } ] ***************** ***************** ProductClass_VariantAttribute: [ { id: 1, productClassId: 1, productAttributeId: 2, isOptional: 0, order: 2 } ] ***************** UPDATED PRODUCT CLASS ProductClass { id: 1, name: 'productclass_name_1', slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ ProductAttribute { id: 3, name: 'attribute_name_3', slug: 'slug_name_3', isOptional: true, dataType: 'float', order: null } ], variantAttributes: [] } AFTER UPDATE ***************** ProductClasses: [ ProductClass { id: 1, name: 'productclass_name_1', slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ [Object] ], variantAttributes: [] } ] ***************** ***************** ProductAttributes: [ ProductAttribute { id: 3, name: 'attribute_name_3', slug: 'slug_name_3', isOptional: false, dataType: 'float' } ] ***************** ***************** ProductClass_ProductAttribute: [ { id: 1, productClassId: 1, productAttributeId: 1, isOptional: 1, order: 1 }, { id: 2, productClassId: 1, productAttributeId: 1, isOptional: 1, order: null }, { id: 3, productClassId: 1, productAttributeId: 2, isOptional: 0, order: null }, { id: 4, productClassId: 1, productAttributeId: 3, isOptional: 1, order: null } ] ***************** ***************** ProductClass_VariantAttribute: [ { id: 1, productClassId: 1, productAttributeId: 2, isOptional: 0, order: 2 }, { id: 2, productClassId: 1, productAttributeId: 2, isOptional: 0, order: null } ] ***************** -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -311,8 +311,8 @@ function* fixtures(knex) { isOptional: true, '#dbRef': 1 }, /* NEW RELATION: This should relate to the current ProductClass with an EXISTING ProductAttribute where ProductAttribute::id = 2 */ { isOptional: false, '#dbRef': 2 -
hetsch revised this gist
Nov 4, 2017 . 1 changed file with 10 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -306,18 +306,18 @@ function* fixtures(knex) { slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ /* OLD RELATION: This is the ProductAttribute that was created in the fixtures */ { isOptional: true, '#dbRef': 1 }, /* NEW RELATION: This should relate the current ProductClass with an EXISTING ProductAttribute with ProductAttribute::id = 2 */ { isOptional: false, '#dbRef': 2 }, /* NEW RELATION: Should create a NEW ProductAtribute and realte it to the current ProductClass */ { name: 'attribute_name_3', slug: 'slug_name_3', @@ -326,14 +326,19 @@ function* fixtures(knex) { } ], variantAttributes: [ /* OLD RELATION: This is the ProductAttribute that was created in the fixtures */ { isOptional: false, '#dbRef': 2 } ] }); console.log('\nUPDATED PRODUCT CLASS\n'); const productClass = await ProductClass.find(1); console.log('\n\n%s\n\n', util.inspect(productClass)); console.log('\nAFTER UPDATE\n'); await dumpData(); -
hetsch created this gist
Nov 4, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,342 @@ import Knex from 'knex'; import objection from 'objection'; import Promise from 'bluebird'; import util from 'util'; function initDatabase() { const knex = Knex({ dialect: 'sqlite3', connection: { filename: ':memory:' }, useNullAsDefault: true, debug: false }); objection.Model.knex(knex); return knex; } class BaseModel extends objection.Model { static get relations() { return []; } static all() { let query = this.query(); if (this.relations.length > 0) { query = query.eager(this.relations); } return query; } static find(id) { let query = this.query() .where('id', parseInt(id, 10)) .first(); if (this.relations.length > 0) { query = query.eager(this.relations); } return query; } static create(data) { objection.transaction(this.knex(), trx => { return this.query(trx).insertGraph(data); }); } static update(data) { objection.transaction(this.knex(), trx => { return this.query(trx) .where('id', data.id) .upsertGraph(data); }); } static delete(id) { objection.transaction(this.knex(), trx => { return this.query(trx) .where('id', parseInt(id, 10)) .delete(); }); } castBooleanFields(json) { const schema = this.constructor.jsonSchema.properties; // const booleanFields = Object.keys(json).filter(key => schema.hasOwnProperty(key) && schema[key].type === "boolean"); for (let [key, value] of Object.entries(json)) { if (schema.hasOwnProperty(key) && schema[key].type === 'boolean') { json[key] = Boolean(value); } } return json; } // SQLITE stores booleans as integers (0 or 1) // Cast them to Booleans, otherwise tcomb-form // throws validation errors that integers are no // booleans. // See: https://github.com/Vincit/objection.js/issues/204 $parseDatabaseJson(json) { let newJson = super.$parseDatabaseJson(json); newJson = this.castBooleanFields(newJson); return newJson; } } class ProductAttribute extends BaseModel { static get tableName() { return 'ProductAttribute'; } static get jsonSchema() { return { type: 'object', properties: { id: { type: 'integer' }, name: { type: 'string' }, slug: { type: 'string' }, dataType: { type: 'string' }, /* extra field on the m2m table */ isOptional: { type: 'boolean' } }, required: ['name', 'slug'] }; } } class ProductClass extends BaseModel { static get relations() { return '[productAttributes, variantAttributes]'; } static get tableName() { return 'ProductClass'; } static get jsonSchema() { return { type: 'object', properties: { id: { type: 'integer' }, name: { type: 'string' }, slug: { type: 'string' }, hasVariants: { type: 'boolean' }, productAttributes: { type: 'array', items: ProductAttribute.jsonSchema }, variantAttributes: { type: 'array', items: ProductAttribute.jsonSchema } }, required: ['name'] }; } static get relationMappings() { return { productAttributes: { relation: objection.Model.ManyToManyRelation, modelClass: ProductAttribute, join: { from: 'ProductClass.id', through: { from: 'ProductClass_ProductAttribute.productClassId', to: 'ProductClass_ProductAttribute.productAttributeId', extra: ['isOptional', 'order'] }, to: 'ProductAttribute.id' } }, variantAttributes: { relation: objection.Model.ManyToManyRelation, modelClass: ProductAttribute, join: { from: 'ProductClass.id', through: { from: 'ProductClass_VariantAttribute.productClassId', to: 'ProductClass_VariantAttribute.productAttributeId', extra: ['isOptional', 'order'] }, to: 'ProductAttribute.id' } } }; } } function* schema(knex) { yield knex.schema.dropTableIfExists('ProductAttribute'); yield knex.schema.dropTableIfExists('ProductClass'); yield knex.schema.dropTableIfExists('ProductClass_ProductAttribute'); yield knex.schema.dropTableIfExists('ProductClass_VariantAttribute'); yield knex.schema.createTable('ProductAttribute', table => { table.bigincrements('id').primary(); table.string('name'); table.string('slug'); table.boolean('isOptional'); table.string('dataType'); }); yield knex.schema.createTable('ProductClass', table => { table.bigincrements('id').primary(); table.string('name'); table.string('slug'); table.boolean('hasVariants'); }); yield knex.schema.createTable('ProductClass_ProductAttribute', table => { table.increments('id').primary(); table .biginteger('productClassId') .unsigned() .references('id') .inTable('ProductClass'); // .onDelete("CASCADE"); // .index(); table .integer('productAttributeId') .unsigned() .references('id') .inTable('ProductAttribute'); // .onDelete("CASCADE"); // .index(); table.boolean('isOptional'); table.boolean('order'); }); yield knex.schema.createTable('ProductClass_VariantAttribute', table => { table.increments('id').primary(); table .biginteger('productClassId') .unsigned() .references('id') .inTable('ProductClass'); // .onDelete('CASCADE'); // .index(); table .integer('productAttributeId') .unsigned() .references('id') .inTable('ProductAttribute'); // .onDelete('CASCADE'); // .index(); table.boolean('isOptional'); table.boolean('order'); }); } function* fixtures(knex) { yield knex .insert({ name: 'attribute_name_1', slug: 'attribute_slug_1', dataType: 'string' }) .into('ProductAttribute'); yield knex .insert({ name: 'attribute_name_2', slug: 'attribute_slug_2', dataType: 'number' }) .into('ProductAttribute'); yield knex .insert({ name: 'productclass_name_1', slug: 'productclass_slug_1', hasVariants: true }) .into('ProductClass'); yield knex .insert({ productClassId: 1, productAttributeId: 1, isOptional: true, order: 1 }) .into('ProductClass_ProductAttribute'); yield knex .insert({ productClassId: 1, productAttributeId: 2, isOptional: false, order: 2 }) .into('ProductClass_VariantAttribute'); } (async () => { const knex = initDatabase(); // DB setup await Promise.each( [Promise.coroutine(schema), Promise.coroutine(fixtures)], func => func(knex) ); const dumpData = Promise.coroutine(function* dump() { const line = '\n\n*****************\n%s:\n\n%s\n*****************\n\n'; console.info(line, 'ProductClasses', util.inspect(yield ProductClass.all())); console.info(line, 'ProductAttributes', util.inspect(yield ProductAttribute.all())); console.info(line, 'ProductClass_ProductAttribute', util.inspect(yield knex.select().from('ProductClass_ProductAttribute'))); console.info(line, 'ProductClass_VariantAttribute', util.inspect(yield knex.select().from('ProductClass_VariantAttribute'))); // yield Promise.resolve(); }); console.log('\nINITIAL DATABASE STATE\n'); await dumpData(); await ProductClass.update({ id: 1, name: 'productclass_name_1', slug: 'productclass_slug_1', hasVariants: true, productAttributes: [ /* The ids of the next two point are the ids of existing ProductAttributes */ { isOptional: true, '#dbRef': 1 }, { isOptional: false, '#dbRef': 2 }, /* This item is a new ProductAttribute item that should be inserted and related with this ProductClass in the m2m table */ { name: 'attribute_name_3', slug: 'slug_name_3', dataType: 'float', isOptional: true } ], variantAttributes: [ /* Allready existing item */ { isOptional: false, '#dbRef': 2 } ] }); console.log('\nAFTER UPDATE\n'); await dumpData(); })(); // Run it with: node --experimental-modules test.mjs