CodeDredd / pinia-orm

The Pinia plugin to enable Object-Relational Mapping access to the Pinia Store.
https://pinia-orm.codedredd.de/
MIT License
454 stars 39 forks source link

Autotomated polymorphic relationships #1945

Open brahmic opened 3 weeks ago

brahmic commented 3 weeks ago

Describe the feature

In the current implementation, when declaring a polymorphic relationship, you must specify a list of models that can be related.

At the same time, a polymorphic relationship implies that the related model can be any and the source of truth is on the backend. Therefore, if a new polymorphic relationship appears in the model for the same field on the backend, in the current implementation of pinia-orm we must add it to the list on the frontend in the same model for the polymorphic field.

The current implementation is not bad, but if the project is large and dynamically developing, then synchronizing the code on the backend with the frontend takes a lot of time.

I have been practicing a method for a long time in my self-written library, which allows you to avoid unnecessary code synchronization and has proven itself well. The meaning is as follows:

  1. All models from the backend contain an identifier key in the response;

    { "id": 1, "foo": "foo", "morphKey": "foo_morph_key" },
    { "id": 1, "bar": "bar", "morphKey": "bar_morph_key" },
  2. On the front, each model has a declaratively written similar key and the type of relationship is specified for the polymorphic field, something like this:

    class User extends Model {
    static morphKey= 'user_morph_key'
    static fields () {
    return {
      attachments: this.morphMany()
    }
    }
    }

    That's all. Thus, when receiving data from the backend, the system will look into the nested structure, extract the identifier key from there, determine and create a model of the required type based on it. There is no longer a need to edit the code on the frontend after changing the connections on the backend. Now, whatever it is connected to, it will immediately work without changes on the frontend.

It would be nice to have such an option in pinia-orm, it greatly speeds up development.

Additional information

Final checks

brahmic commented 3 weeks ago

A compromise solution could be like this:

export default class Image extends Model {
  static entity = 'image'

  // will return related polymorphic models computed from the original data received from the backend
  getKeys (modelData) {
    const keys = modelData.imageable.map((relatedModelData) => relatedModelData.morphKey)
    return modelMap.filter(model => keys.includes(model.morphKey))
  }

  static fields() {
    return {
      id: this.number(0),
      url: this.string(''),
      imageableId: this.number(0),
      imageableType: this.string(''),
      imageable: this.morphTo(
          this.getKeys,
          'imageableId',
          'imageableType',
          'morphableId'
      )
    }
  }
}

I don't know how pinia-orm works under the hood, but if someone could explain it, maybe I could cope with this task.