[RFC] Enable inserting and retrieving custom relationships in STI
Type of PR:
- [x] Bugfix
- [x] Feature
- [ ] Code style update
- [x] Refactor
- [ ] Build-related changes
- [ ] Documentation
- [ ] Other, please describe:
Breaking changes:
- [x] No
- [ ] Yes
Details
Fixes https://github.com/vuex-orm/vuex-orm/issues/606, https://github.com/vuex-orm/vuex-orm/issues/581, https://github.com/vuex-orm/vuex-orm/issues/519, https://github.com/vuex-orm/vuex-orm/issues/606, https://github.com/vuex-orm/vuex-orm/issues/512, https://github.com/vuex-orm/vuex-orm/issues/443
TL;DR
This PR enables users to do something like:
await Person.insert({
data: [
{ id: 1, name: 'John' },
{
id: 2,
name: 'Jane',
type: 'ADULT',
jobs: [
{
id: 1,
title: 'jack of all trades'
},
{
id: 2,
title: 'Software engineer',
type: 'office',
building: { id: 1, address: 'Park Avenue' }
},
{
id: 3,
title: 'Designer',
type: 'remote',
locations: [{ id: 1, lat: 12, lng: 34 }, { id: 2, lat: 56, lng: 78 }]
}
]
},
]
})
console.log(Person.query().withAllRecursive().get())
[ Person { '$id': '1', id: 1, name: 'John', type: '' },
Adult { '$id': '2', id: 2, name: 'Jane', type: 'ADULT', title: '', jobs: [
Job { '$id': '1', id: 1, type: null, title: 'jack of all trades', adult_id: 2 },
OfficeJob { '$id': '2', id: 2, type: 'office', title: 'Software engineer', adult_id: 2, building:
Building { '$id': '1', id: 1, address: 'Park Avenue', buildingable_id: 2, buildingable_type: 'job' } },
RemoteJob { '$id': '3', id: 3, type: 'remote', title: 'Designer', adult_id: 2, locations: [
Location { '$id': '1', id: 1, lat: 12, lng: 34, locationable_id: 3, locationable_type: 'job' },
Location { '$id': '2', id: 2, lat: 56, lng: 78, locationable_id: 3, locationable_type: 'job' } ] } ] } ]
I will clarify the specific refactors in separate comments. This is not a breaking change but will definitely need to be tested well before merging into master.
Please bear in mind I'm a noob when it comes to Typescript and contributing to vuex-orm so if there are any hiccups it would be nice if you guided me through them ❤️
How it comes, that I always need features which are not quite ready yet...
Is this branch ok enough to test/develop with? I really would like to use it.
Hey @Fuzzyma, I'm using this branch on my local dev environment but I'd not recommend to use that in production. Try it out and if you find something broken please let me know.
@kiaking, I'm curious if this is going to be sorted out in vuex-orm-next? Looks like it's a complete rewrite so I think it's unlikely this PR will be relevant for 1.0.0 version.
Edit: Also make sure to build this this branch of vuex-orm before using it
I'm using this https://github.com/petertoth/vuex-orm/tree/fix-custom-relationships-derived-models-dist
I just tried to build it and got an error in Query.ts:
semantic error TS2698: Spread types may only be created from object types.
I cloned your given branch and npm installed all dependencies and run npm run build.
Anything else I need to check?
You actually don't need to build it again if you're using the branch I mentioned earlier. Just replace vuex-orm in your package.json like:
{
"dependencies": {
"@vuex-orm/core": "petertoth/vuex-orm#fix-custom-relationships-derived-models-dist"
}
}
And do a fresh install
Thanks for this PR @petertoth. Looks like an incredible amount of effort went into this and we really appreciate your time. It is unlikely this PR will be merged since all our efforts are focused on the @next repo.
I'm curious if this is going to be sorted out in
vuex-orm-next? Looks like it's a complete rewrite so I think it's unlikely this PR will be relevant for1.0.0version.
While this PR would be incompatible with 1.0.0, we are keen to keep it open to provide insight and guidance when this feature is implemented in the @next repo. I'm sure we'll be picking at your brain in due course.
@cuebit do you have a timeframe in mind when 1.0 will get released?
@petertoth branch seems to work as expected
@cuebit do you have a timeframe in mind when 1.0 will get released?
Currently working to the timeline set out by Vue 3 and it’s release which will be around August time but I cannot guarantee a fixed date at this time.
@cuebit does that mean, that 1.0 will be only compatible to Vue 3?
@petertoth I found something that I would consider a bug but I am not sure if it is intended.
When I create a new subclass of something, the type key is set to the default value I specified in the base class. It kinda makes sense to value the default property but I would have expected that the type is set correctly to the type of the subclass.
I solved it by overwriting the type field in my subclass with the correct type as default value.
What do you think?
@Fuzzyma Could you provide a code snippet with described behavior?
class Animal extends Model {
entity: 'animals'
static fields () {
return {
id: this.attr(null),
type: this.attr('animal')
}
}
static types () {
return {
animal: Animal,
dog: Dog
}
}
}
class Dog extends Animal{
entity: 'dogs'
baseEntity: 'animals'
static fields () {
return {
...super.fields(),
type: this.attr('dog') // add this to make it work
}
}
}
// type is animal when the fix above isnt used
cost dog = new Dog()
PS: I wrote this on top of my head. But it should show the issue I am having
I found one missing fix in the Model.commit method. It is giving you the entitys data instead of the baseEntitys one. And this is always empty.
e.g. Rect extends Shape Model:
store.state.entities.rects.data // empty
store.state.entities.shapes.data // all the shapes including rects
That's why the code should be something like this:
Model.commit = function (callback) {
this.store().commit(this.database().namespace + "/$mutate", {
entity: this.baseEntity || this.entity, // this is changed
callback: callback
});
};