Propagation of ManyToOne back to collections
See original GitHub issueI’m writing some business logic / tests that creates / updates entities based on the ManyToOne
side of a relation, and later looks / asserts against the OneToMany
side of that same relation, but it is empty.
I.e.:
it("should update posts", () => {
const author = new Author();
const post = new Post();
post.author = author.toReference();
expect(author.posts.getItems()).toContain(post);
});
At first I thought this was a bug in getItems()
thinking that the collection was initialized when really it was not. However, that is not the case, the collection is initialized (as empty since Author
is a new entity), it’s just not being kept up-to-date as the post.author
field changes.
This means that to correctly have author.posts.getItems()
to have the correct value, I have to: a) flush the author and post entities to the db, b) reload the author entity and c) init its collection.
This turns the unit of work / entities / collections into a leakier abstraction, as now I need to realize collections might return invalid values that don’t respect the work-in-progress that exists in the rest of my unit of work. (I.e. I think ideally the unit of work is supposed to represent a unified / update-to-date view of currently-loaded entities, i.e. instead of re-fetching a row from the db everytime and missing “oh we’ve changed the author’s name in this UoW so use that value”).
So, I’d like to see this “we have some WIP and everyone sees that WIP consistently” behavior of the unit of work extended from primitives to these collections.
…all that said, it looks like the docs already highlight this propagation works if relationships are setup through the Collection.add/remove
methods, I’d just like to see the same thing happen on the other side, so that my code doesn’t have to be coupled to “to get the most consistent behavior out of Mikro, we always need to modify relationships via the Collection
side”.
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (6 by maintainers)
So I finally cracked all of the problems that this change uncovered. They were all there but not visible as one usually do not make the relation fully propagated in the entity graph.
As part of the refactorings I had to introduce commit order calculator, pospone m:n collection queries, also there were bugs in EntityFactory.
Will try to split the work into multiple commits now so all the changes are visible in the history, but finally all tests are now passing.
Not sure what you mean, getter would always return, only setter in this case would propagate the change when the inverse side (1:m collection) is initialized (as you cannot modify collection that is not).
Already got this implemented and it works fine, with a downside of
console.log(entity)
not printing getter properties by default. That can be solved byinspect.custom
, but it’s kinda tricky to implement it correctly (computing correct padding for nested objects). Now I am trying to use this also for 1:1, but there few failing tests.Here is the code for patching the prototype: