vuex-orm / vuex-orm

The Vuex plugin to enable Object-Relational Mapping access to the Vuex Store.
https://vuex-orm.org
MIT License
2.36k stars 166 forks source link

Improve the ORM relationship and methods #311

Open dousybox opened 5 years ago

dousybox commented 5 years ago

I have collected some useful ORM relationships, and try to corresponding them to Vuex ORM methods.

But some of them have no corresponding methods.

Can anyone help me improve the table below?

normal

Relation Method Mapping Example
One To One hasOne 1 -> 1 User.id -> Profile.user_id
Inverse One To One belongsTo 1 -> 1 Profile.user_id -> User.id
One To Many hasMany 1 -> N User.id -> Post.user_id
Inverse One To Many belongsTo N -> 1 Post.user_id -> User.id
One To Many with pivot ???? 1 -> N User.id -> pivot -> Post.id
Inverse One To Many with pivot ???? N -> 1 Post.id -> pivot -> User.id
Declarar To Many hasManyBy N -> N Group.user_ids -> User.id
Inverse Declarar To Many ???? N -> N User.id -> Group.user_ids
Many To Many with pivot belongsToMany N -> N User.id -> pivot -> Role.id
Inverse Many To Many with pivot belongsToMany N -> N Role.id -> pivot -> User.id

Through

Relation Method Mapping Example
One To One Through ???? 1 -> 1 -> 1 Avatar.user_id -> User.id -> Profile.user_id
Inverse One To One Through ???? 1 -> 1 -> 1 Profile.user_id -> User.id -> Avatar.user_id
One To Many Through hasManyThrough 1 -> 1 -> N Country.id -> User.country_id|user_id -> Posts.user_id
Inverse One To Many Through ???? N -> 1 -> 1 Post.user_id -> User.user_id|country_id -> Country.id
One To Many Through ???? 1 -> N -> N User.id -> Posts.user_id|id -> pivot -> Tags.id
Inverse One To Many Through ???? N -> N -> 1 Tag.id -> pivot -> Posts.id|user_id -> User.id
Many To Many Through ???? N -> N -> N User.id -> pivot -> Role.id -> pivot -> Permissions.id
Inverse Many To Many Through ???? N -> N -> N Permissions.id -> pivot -> Roles.id -> pivot -> Users.id

Polymorphic

Relation Method Example
Polymorphic One To One morphOne Post/Video - Cover
Inverse Polymorphic One To One morphTo Cover - Post/Video
Polymorphic One To Many morphMany Post/Video - Comments
Inverse Polymorphic One To Many morphTo Comments - Post/Video
Polymorphic Many To Many morphToMany Posts/Videos - Tags
Inverse Polymorphic Many To Many morphedByMany Tags - Posts/Videos
kiaking commented 5 years ago

@dousybox Hi! Thank you for the detailed map! This is amazing. Coming from Laravel backend, I didn't know most of this. I'm not sure if Vuex ORM should have full set, but sure this issue is going to be a dictionary to look up when considering a new relationship implementation.

I would like to focus on other issue that stopping Vuex ORM hitting v1.0.0, but I would like to keep this issue open until we make decision on these relationship.

dousybox commented 5 years ago

@kiaking Thank you for your recognition, I'm very glad that it can be useful.

These table are the referrances that I used to find relational functions in my project.

When I sorted out the mapping table, I found that some relationships did not appear in the documents.

So I searched somthing about orm, then find out the Laravel framework.

And refer to it to fill out my mapping table, and added more relations about Through Relations.

You're right, these relation mappings are not the primary issue.

They have not to be optimized yet, especially the Through Relations. Some relationships seem to be duplicates, I'm still thinking.

This project are really awesome, I'm very happy to help it.

kiaking commented 5 years ago

@dousybox Thanks! I think this mapping is pretty useful in general. Since these kind of things are tend to be different on every frameworks (even the names).

FrittenKeeZ commented 4 years ago

I could really use "Many To Many Through" for this exact reason: User.id -> pivot -> Role.id -> pivot -> Permissions.id

Currently you have to make a custom getter to make this work.

cuebit commented 4 years ago

@FrittenKeeZ yea we should really support through relations on all relation types.

As a side note, a getter is a more performant way of retrieving m:t:m relations.

FrittenKeeZ commented 4 years ago

Sure, if you can cache the result in some way. I don't know whether this is the most efficient way really...

/**
 * Get unique permissions through roles.
 *
 * @return {Permission[]}
 */
get permissions () {
  return [...new Set(this.roles.map(role => role.permissions).flat())].sort((a, b) => a.name.localeCompare(b.name))
}

/**
 * Whether user has the given permission.
 *
 * @param {String} name
 *
 * @return {Boolean}
 */
hasPermission (name) {
  let permissions = this.$store().getters['auth/permissions']
  if (permissions === null) {
    // Commit permissions to store for better performance.
    permissions = this.permissions.map(permission => permission.name)
    this.$store().commit('auth/permissions', permissions)
  }

  return permissions.includes(name)
}