Strongloop: HasAndBelongsToMany Polymorphic Relationship with uuids
I am trying to use HasAndBelongsToMany polymorphic relation when using uuids. My problem is that I cannot teach Strongloop to use an id with a string as a type instead of a number in the required many-to-many table. This leads to SQL errors when creating new relationships.
Let me explain, for example:
I have two models: CartCollection and Cart. The collection should have different carts, including the cart itself. Cart and CartCollection have uuids instead of simple IDs. Show this as a property in model-json. The problem lies in the many-to-many polymorphic relationships between them. I am trying to use the HasAndBelongsToMany polymorphic relationship to figure this out. In this table, I am also trying to override the id type.
This is my JSON code:
{
"name": "SaleCartCollection",
"plural": "SaleCartCollections",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "string",
"length": 36,
"id": true
}
},
"validations": [],
"relations": {
"saleCartsPoly": {
"type": "hasMany",
"model":"SaleCart",
"polymorphic" : {
"as": "saleCartsPoly",
"invert": true
},
"through": "SaleCartCartCollectionLink"
}
},
"acls": [],
"methods": []
}
{
"name": "SaleCart",
"plural": "SaleCarts",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"type": "string",
"length": 36,
"id": true
}
},
"validations": [],
"relations": {
"SaleCartCollections": {
"type": "hasAndBelongsToMany",
"model": "SaleCartCollection",
"polymorphic": {
"as":"saleCartsPoly",
"foreignKey" : "saleCartsPolyId",
"discriminator" : "saleCartsPolyType"
},
"through": "SaleCartCartCollectionLink"
}
},
"acls": [],
"methods": []
}
{
"name": "SaleCartCartCollectionLink",
"base": "PersistedModel",
"properties": {
"saleCartsPolyId": {
"type": "string",
"length": 36
}
},
"validations": [],
"relations": {
},
"acls": [],
"methods": []
}
If I now try to POST a new CartCollection to an existing cart, I get this output:
loopback:connector:mysql SQL: INSERT INTO `SaleCartCartCollectionLink`(`saleCartsPolyId`,`saleCartsPolyType`,`saleCartCollectionId`) VALUES(?,?,?), params: [null,"SaleCart","bad7a6fc-1798-49c5-a0cb-fa59eba5b3a4"] +8ms
loopback:connector:mysql Error: {"code":"ER_BAD_FIELD_ERROR","errno":1054,"sqlState":"42S22","index":0} +11ms
I found out this was happening because Strongloop was ignoring my property definition in Through-model. It's still a number that you can see here in the model schematic in explorer:
[
{
"saleCartsPolyId": 0,
"id": 0,
"saleCartsPolyType": "",
"saleCartCollectionId": ""
}
]
Does anyone have an idea if I am doing something wrong or if this is a bug in Strongloop?
Regards
Niklas
source to share
I am Niklas's employee, and we solved our problem as follows.
We define
- "Cart hasMany CartCollection via CartCartCollectionLink" relation is polymorphic "like a cart"
- "CartCollection hasMany Cart via CartCartCollectionLink" polymorphic "as cartCollection"
- and here's the important part: the two polymorphic "CartCartCollectionLink belongs to [Cart | CartCollection]" relationships are polymorphic with polymorphic .idType: string !
The interesting part is that the idType property is incorrectly set for the HasAndBelongsToMany relationship.
Someone might want to take a look at relation-definition.js: 1566:
if (params.polymorphic) {
var polymorphic = polymorphicParams(params.polymorphic);
options.polymorphic = polymorphic; // pass through
var accessor = params.through.prototype[polymorphic.as];
if (typeof accessor !== 'function') { // declare once
// use the name of the polymorphic rel, not modelTo
// *** you might want to set idType here: ***
params.through.belongsTo(polymorphic.as, { polymorphic: true });
}
}
CartCartCollectionLink.json
{
"name": "SaleCartCartCollectionLink",
"relations": {
"saleCarts": {
"type": "belongsTo",
"model": "SaleCart",
"foreignKey": "saleCartId",
"polymorphic": {
"as": "saleCart",
"idType": "string"
}
},
"saleCartCollections": {
"type": "belongsTo",
"model": "SaleCartCollection",
"foreignKey": "saleCartCollectionId",
"polymorphic": {
"as": "saleCartCollection",
"idType": "string"
}
}
}
}
Cart.json
{
"name": "SaleCart",
"properties": {
"id": {
"type": "string",
"length": 36,
"id": true
}
},
"relations": {
"saleCartCollections": {
"type": "hasMany",
"model": "SaleCartCollection",
"foreignKey": "saleCartId",
"through": "SaleCartCartCollectionLink",
"polymorphic": {
"as": "saleCart"
}
}
}
}
CartCollection.json
{
"name": "SaleCartCollection",
"properties": {
"id": {
"type": "string",
"length": 36,
"id": true
}
},
"relations": {
"saleCarts": {
"type": "hasMany",
"model": "SaleCart",
"foreignKey": "saleCartCollectionId",
"through": "SaleCartCartCollectionLink",
"polymorphic": {
"as": "saleCartCollection"
}
}
}
}
source to share