pinia-orm icon indicating copy to clipboard operation
pinia-orm copied to clipboard

ManyToMany doesn't remove relation on save()

Open karsvaniersel opened this issue 11 months ago • 4 comments

Environment

No response

Reproduction

Rather obvious since everything is according to the docs :)

Describe the bug

Can follow the docs for the ManyToMany relation setup.

This only happens on remove, adding relations works fine.

Initial:

{
  entities: {
    users: {
      1: { id: 1, name: 'John Doe' }
    },
    posts: {
      1: { id: 1, userId: 1, title: 'Title A' },
      2: { id: 2, userId: 1, title: 'Title B' }
    }
  }
}
// The user record.
const user = {
  id: 1,
  name: 'Jane Doe',
  posts: [
    { id: 1, userId: 1, title: 'Title C' },
    { id: 2, userId: 2, title: 'Title D' }
  ]
}
// Insert the user record.
useRepo(User).save(user)
// The result inside the store.
{
  entities: {
    users: {
      1: { id: 1, name: 'Jane Doe' } // <- Updated.
    },
    posts: {
      1: { id: 1, userId: 1, title: 'Title C' }, // <- Updated.
      2: { id: 2, userId: 1, title: 'Title D' }  // <- Updated.
    }
  }
}

Removing a post relation:

{
  entities: {
    users: {
      1: { id: 1, name: 'John Doe' }
    },
    posts: {
      1: { id: 1, userId: 1, title: 'Title A' },
      2: { id: 2, userId: 1, title: 'Title B' }
    }
  }
}
// The user record.
const user = {
  id: 1,
  name: 'Jane Doe',
  posts: [
    { id: 1, userId: 1, title: 'Title C' },
    // note that we removed the post with id 2 here
  ]
}
// Insert the user record.
useRepo(User).save(user)
// The result inside the store.
{
  entities: {
    users: {
      1: { id: 1, name: 'Jane Doe' }
    },
    posts: {
      1: { id: 1, userId: 1, title: 'Title C' },
      2: { id: 2, userId: 1, title: 'Title D' }  // <- Not deleted.
    }
  }
}

Also this doesn't trigger the deleting and deleted lifecycle hook on the intermediate table. If you add a relation, it does trigger creating and created. So I assume the lifecycle hooks do work, just not on deletion?

Am I completely doing something wrong or missing something?

karsvaniersel avatar Mar 11 '24 06:03 karsvaniersel

I think it is a bad idea to remove posts that are not there in the save call. Because the current behavior allows to only insert the new posts. Because if you have a lot of posts it is very annoying (and very performance intensive) that you need to insert all the posts every time you want to add one posts.

So just delete the posts you want to delete separately.

tintin10q avatar Mar 27 '24 12:03 tintin10q

Aah oke, I see! Well thanks for the explanation :)

Maybe in the future this could be an option of some sorts? Like saveFlush() or saveDeep().

Altho running a regular save() followed by a useRepo(Post).destroy(2) is not that big of a drawback.

karsvaniersel avatar Mar 29 '24 23:03 karsvaniersel

So how do I remove an intermediate table tho? Cause not deleting the actual Post is fine, but it should delete the relation which is not happening.

karsvaniersel avatar Mar 31 '24 00:03 karsvaniersel

So for other people having the same issue, a quick / dirty fix:

Instead of just running save() useRepo(User).save(user)

You do: useRepo(UserPost).where('user_id', user.id).delete() useRepo(User).save(user)

This clears out all the UserPost relations for given user id. Then the save() function correctly adds the new ones.

karsvaniersel avatar Mar 31 '24 00:03 karsvaniersel

@karsvaniersel You should use the saving hook for your deleting. That way you get what you want because @tintin10q is right. Saving should not trigger the deleting hook if some relation changed.

CodeDredd avatar May 04 '24 19:05 CodeDredd

Thanks for your response :) And happy to see you back! Absolutely love this package 👍

karsvaniersel avatar May 04 '24 19:05 karsvaniersel

@karsvaniersel Thanks a lot ❤️ .

CodeDredd avatar May 04 '24 20:05 CodeDredd