data icon indicating copy to clipboard operation
data copied to clipboard

Polymorphic relationships

Open lavoscore opened this issue 4 years ago • 4 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(...) })

lavoscore avatar Sep 29 '21 17:09 lavoscore

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({/*...*/})

kettanaito avatar Oct 05 '21 15:10 kettanaito

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.

lavoscore avatar Oct 05 '21 18:10 lavoscore

What's the verdict on this?

NuktukDev avatar Dec 10 '23 09:12 NuktukDev

@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.

kettanaito avatar Dec 16 '23 11:12 kettanaito