Skip to content

Conversation

@nduitz
Copy link
Contributor

@nduitz nduitz commented Mar 13, 2025

Hey there,
I tried my best to add support for polymorphic resources.
The idea is to allow the user to infer resource specifics from the given data.
Currently this only allows type and fields to be polymorphic. I will probably implement relationships as well.

Additionally I only tested it to work as a relation with an api endpoint of its own - quite frankly there are some things that are not possible:
The QueryParser fetches view.fields() at a moment where no data is present, thus inference is not possible.

This is my first time really working with a behaviour, my approach on implementing a backwards compatible solution felt a bit clunky, so any feedback is very welcome. :)

@nduitz nduitz requested a review from a team as a code owner March 13, 2025 10:48
@mattpolzin
Copy link
Member

Thanks for the PR. I’m on a trip for the next two weeks so unless someone else jumps in there will be a bit of a delay in looking this over. Just wanted to let you know I see the PR!

@mattpolzin mattpolzin self-requested a review March 14, 2025 22:01
@doomspork doomspork changed the title add backwards compatible polymorphic resource support feat: add backwards compatible polymorphic resource support Mar 15, 2025
Copy link
Member

@mattpolzin mattpolzin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a pretty reasonable approach to me. I'll do a bit more thinking on it but in the meantime there are a few things I found to comment on.

@nduitz nduitz force-pushed the polymorphic_resources branch from ee95988 to fa2d880 Compare April 10, 2025 09:45
@nduitz
Copy link
Contributor Author

nduitz commented May 6, 2025

Hey there,
thanks for your feedback and sorry for the long period of silence.
I had a lot of work to do and made some additions to this I am currently using with no problems at all.
I will try to implement your suggestions soon :)

@nduitz
Copy link
Contributor Author

nduitz commented Jun 5, 2025

Hey there :)
I did some refactoring of my first approach.
WDYT?
Additionally I updated the docs to get a better understanding of what is possible and how to use the functionality.

@mattpolzin mattpolzin self-requested a review June 13, 2025 17:43
@mattpolzin
Copy link
Member

Hey! Sorry, I kept not thinking of this PR when I had time to look at it because it had been removed from my review queue after my previous comments. I've added it back into my queue so I should get this reviewed in the next few (week) days.

Copy link
Member

@mattpolzin mattpolzin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good. I only have one inline comment.

I do have one high level question, though. Is it better (or more versatile) or just different to do it the way you've got it in this PR -- separate functions for type, fields, and relationships that take data and determine a result based on it -- versus having a mechanism by which a View can choose a more specific other View module so that you could implement your polymorphism via say 3 distinct JSONAPI.View modules (in the old style already supported by this library) and have one new JSONAPI.View module that had a single function that took the data and returned the module of the 3 possibilities that should be used for that data.

@nduitz
Copy link
Contributor Author

nduitz commented Jul 1, 2025

This looks pretty good. I only have one inline comment.

I do have one high level question, though. Is it better (or more versatile) or just different to do it the way you've got it in this PR -- separate functions for type, fields, and relationships that take data and determine a result based on it -- versus having a mechanism by which a View can choose a more specific other View module so that you could implement your polymorphism via say 3 distinct JSONAPI.View modules (in the old style already supported by this library) and have one new JSONAPI.View module that had a single function that took the data and returned the module of the 3 possibilities that should be used for that data.

Hm I'd have to go over my approach vs the approach you described. Could you give me a short example on how that would look like? I can't seem to find any example for that in the docs, maybe it is maintainer knowledge? :P

@mattpolzin
Copy link
Member

This looks pretty good. I only have one inline comment.
I do have one high level question, though. Is it better (or more versatile) or just different to do it the way you've got it in this PR -- separate functions for type, fields, and relationships that take data and determine a result based on it -- versus having a mechanism by which a View can choose a more specific other View module so that you could implement your polymorphism via say 3 distinct JSONAPI.View modules (in the old style already supported by this library) and have one new JSONAPI.View module that had a single function that took the data and returned the module of the 3 possibilities that should be used for that data.

Hm I'd have to go over my approach vs the approach you described. Could you give me a short example on how that would look like? I can't seem to find any example for that in the docs, maybe it is maintainer knowledge? :P

Sorry for the delay. I've been busy enough at work that I haven't and still don't have time to reply in detail. The suggestion was not to follow an existing pattern found elsewhere in this library, just a high level alternative idea.

In broad strokes, you could have a callback like the following:

@callback polymorphic_specialization(data()) :: module()

As an alternative to several callbacks for polymorphic relationships, attributes, etc.

Then you could define "regular" View modules for each specialization (by regular I just mean they don't look polymorphic). You would return the correct specialized view module from polymorphic_specialization/1 and from there the rest of the library's code would operate the same way it always has but using that specialized view instead of a predetermined one.


Regardless, don't worry if you don't have time to think on that approach. Instead, give my inline comment a reply and we can move forward with this PR because it looks like it does the trick and does not break anything and it's a very nice feature to have.

@nduitz
Copy link
Contributor Author

nduitz commented Aug 8, 2025

Ahh now I get it, thanks for the clarifaction. Let me have a look, I like the idea of it!

@nduitz
Copy link
Contributor Author

nduitz commented Aug 8, 2025

So I gave it a go but I am not really fluent in meta programming.
I don't really have the time to dig deeper as of now so I decided to respect your comment about recource_x don't need to be callbacks instead. hope that is okay :)

Copy link
Member

@mattpolzin mattpolzin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for thinking through some of this in response to my questions and comments. This looks good and it will be nice to have support for polymorphic resources in this way.

@mattpolzin mattpolzin changed the title feat: add backwards compatible polymorphic resource support feat: add polymorphic resource support Aug 19, 2025
@mattpolzin mattpolzin merged commit 0ea2996 into beam-community:main Aug 19, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants