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

Feature Request: Polymorphic Reference Folding

Open TylerR909 opened this issue 2 years ago • 1 comments

It'd be cool to be able to both load and fold on Polymorphic references. Something like...

const author = await em.findOne(
  Author,
  {},
  {
    populate: {
      // Poly on Book | Blogpost | Article
      latest: {
        _book: ["name", "chapters", "store"],
        _blogpost: ["siteName", "link"],
        _article: ["publication", "url"],
      },
    },
  },
);

const currentBlurb = author.latest.fold({
  Book: (b) => `${b.name} now available at ${b.store.get.name}`, // `b` is Loaded
  Blogpost: (bp) => `See the latest from ${author.name} at ${bp.siteName} (${bp.link})`,
  Article: (a) => `${a.publication.get.name} recently wrote about ${author.name}. See what they had to say! (${a.link})`,
});

This TypeScript type might be helpful.

It might be nice to avoid .get if possible, to save a few chars. Not sure how that might play out in Arrays, i.e. if "Reviews" was a poly array on UserReview | PublicationReview would the preferred syntax be Book.reviews.get.map((poly) => poly.fold({ ... }))?

I think this would scale pretty well to Async Properties, derived fields, maybe some Persisted stuff, Hooks, etc.

TylerR909 avatar Aug 16 '23 20:08 TylerR909

Nice--I had thought of a syntax, extremely similar, like:

const author = await em.findOne(
  Author,
  {},
  {
    populate: {
      // Poly on Book | Blogpost | Article
      latest: {
        Book: ["name", "chapters", "store"],
        BlogPost: ["siteName", "link"],
        Article: ["publication", "url"],
      },
    },
  },
);

As well about a week ago, when wanting to do something fancy / "looking through the poly" with Collaboration / CollaborationParent.

I like fold, but would probably shy away from pulling it into Joist proper, as I think idiomatic Joist, for better or worse, is to expect the .get, and better to be consistent iom.

Ideally the ^ snippet would turn latest.get into Loaded<Book, ...> | Loaded<BlogPost, ...> | Loaded<Article, ...> and then the user could do instanceofs on each of them.

Eh, maybe the fold would be worth it.

stephenh avatar Aug 20 '23 22:08 stephenh