mswjs / data

Data modeling and relation library for testing JavaScript applications.

Home Page:https://npm.im/@mswjs/data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Polymorphic relationships

lavoscore opened this issue · comments

Any chance of having support for polymorphic relations? Like:

export const db = factory({
  comment: {
    // ...
    commentable: oneOf('commentable', { polymorphic: true })
  },

  post: {
    // ...
    comments: manyOf('comment', { as: 'commentable' })
  },

  image: {
    // ...
    comments: manyOf('comment', { as: 'commentable' })
  }
})

db.comment.create({ commentable: db.post.create(...) })

Hey, @lavoscore. Thank you for mentioning this.

We should add support for polymorphic relationships (associations) to the library. Before we do that, I'd like to clarify the expected behavior and supposed API.

Declaration

const db = factory({
  comment: {
    commentable: polymorphic()
  },
  post: {
    comments: manyOf('comment')
  },
  image: {
    comments: manyOf('comment')
  }
})

Creating a polymorphic relationship

// Create a comment for a post.
db.comment.create({
  commentable: db.post.findOne({/*...*/})
})

// Create a comment for a user.
db.comment.create({
  commentable: db.user.findOne({/*...*/})
})

Querying polymorphic relationships

// Query all comments for all posts.
db.comment.findMany({
  where: {
    commentable: {
      type: {
        // The type strictly equals the model name
        // listed in the model dictionary.
        equals: 'post'
      }
    }
  }
})
// Query all comments for a single image.
db.comment.findMany({
  where: {
    commentable: {
      type: { equal: 'image' },
      id: { equal: someImage.id }
    }
  }
})

// Get comments for a particular post
// from the queried post entity.
const { comments } = db.post.findOne({/*...*/})

Looks much better! Loving the project, but currently I'm struggling with this as I need to work with polymorphic models. My workaround is to work with several exclusive properties, which is very cumbersome. Something like this:

const db = factory({
  comment: {
    commentable: String,
    commentableAsPost: oneOf('post'),
    commentableAsImage: oneOf('image'),
    // ... every new polymorphic goes here :'(
  },
})

And then writing helpers to detect which property has data and JSON.stringify it into commentable. And later JSON.parse commentable into the final object. Handling polymorphism would allow me to get rid of all that.

What's the verdict on this?

@NuktukDev, polymorphic relationships will land eventually but not before the 2.0 rewrite of Data. They are too much work and I'd rather them not block the rewrite. I would love to make it happen sometime next year.