Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polymorphic Associations #6050

Closed
duhruh opened this issue Jun 19, 2014 · 33 comments
Closed

Polymorphic Associations #6050

duhruh opened this issue Jun 19, 2014 · 33 comments

Comments

@duhruh
Copy link

duhruh commented Jun 19, 2014

This is more of a question rather than an issue and the title speaks for itself. Are there any plans to support polymorphic associations in the future, much like how active record handles them?

@particlebanana
Copy link
Contributor

Absolutely! We haven't gotten around to it yet but after 0.10 is officially released I would like to take a look at this.

@kevinob11
Copy link

Couple of questions...

  1. What is a good workaround prior to this being implemented? I've got a really simple use case Phone Number which could be associated with a company or a user. Any idea on a way to structure this for now to avoid too much rework later?

  2. Where can I get started helping get this implemented faster? I'm pretty good with js client side, but just started working with it server side and I still struggle a bit groking the structure.

I'll start digging through code and figure out what I can, any guidance would be great.

@CWyrtzen
Copy link

CWyrtzen commented Aug 1, 2014

@kevinob11 did you take your question to any of the other forums?

Contribution Guide | Stackoverflow | Google Group | Trello | IRC | Build Status

note to self: change milestone back to FR after reply~

@kevinob11
Copy link

I haven't, but I'm happy to!

Also, in case anyone else is looking here, the workaround I used isn't really a workaround at all. I just realized that in limited cases such as mine where I'm just looking to relate a phone number to multiple other models just using columns for each model in the phone number model isn't too much of a limitation. In my situation I was only ever accessing it from the other model, and the structure on that end will never change. To get specific:

Companies and People have Phone Numbers

A phone number can have a Company or a Person, as different separate properties.

When I finally make the change over to polymorphic I can just add the polymorphic "parent" column, migrate the data over, and adjust the definition (but not the structure) of the phoneNumbers property on my Company and Person models.

Anyway I'll reach out in the forums and see if I can get enough info to actually do some work on this.

@CWyrtzen
Copy link

CWyrtzen commented Aug 1, 2014

Great! We'll keep it open while you hunt for some input. Let us know what you get, thanks~

@wolfie82
Copy link

wolfie82 commented Aug 3, 2014

👍 I can't hardly wait until models have the ability to represent polymorphism. For me it makes structuring reusable models so much easier.

@tjwebb
Copy link
Contributor

tjwebb commented Aug 9, 2014

+1

@tjwebb
Copy link
Contributor

tjwebb commented Aug 10, 2014

@patbaker82 btw, I think this issue is about polymorphic associations, not polymorphic inheritance. Is that what you mean?

@tjwebb
Copy link
Contributor

tjwebb commented Aug 10, 2014

One strategy for designing unidirectional one-to-many relations might be as follows. Feedback is appreciated. I have not tried this.

Create a HasMany waterline Model:

  • HasMany
    • parentType, parent (foreign key), child (foreign key)

Say I have User and Customer that both have a one-to-many relation to Preference. I might define the models like so:

User and Customer

{ 
  attributes: {
    ...
    preferences: {
      collection: 'Preference',
      via: 'parent'
    }
}

Preference

{
  attributes: {
    ...
    parent: {
      type: 'integer',
      polymorphic: true
    }
}

During the pertinent lifecycle callbacks, this additional join could be resolved using parentType and parent, and user.populate('preferences') would return a list of Preference objects. Maybe if we only want to associate some models but not all, we could say something like:

parent: {
  model: [ 'User', 'Customer', 'Agent' ],
  polymorphic: true
}

Does this high-level description make approximate sense?

@ghost
Copy link

ghost commented Apr 17, 2015

any news on this?

@dmarcelino
Copy link
Member

@onceatime, this is not slated for 0.11 so it will probably take some time. Having said that, any help would be welcomed!

@ghost
Copy link

ghost commented Apr 17, 2015

ok will look into waterline and try to help. my situation is this i use ember as a frontend end sails as my api provider ( wont go back to rails again ). In ember i have pages and posts both of them are commentable.

do you see any workaround for this ( without blowing everything up with multiple models )....

in sails i have this for my page ( and also posts )

comments: {
  collection: 'comment',
  via: 'commentable'
}

and in comment ( right now )

commentable: {
  model: 'page'
}

what i can do is something like

commentablePage: {
  model: 'page'
},
commentablePost: {
  model: 'post'
}

but this feels ugly ;-)

any ideas?
in my mind a good syntax would be:

commentable: {
  model: ['page', 'post']
},
commentableType: {
  type: 'string'
}

for now i start to dive into waterline and have a look for possible implementations

@pixelig
Copy link

pixelig commented Jun 25, 2015

Any news here?

@onceatime i'm stuck with the same problem (also using ember as frontend). Did you find a solution or some kind of workaround?

@smyth64
Copy link

smyth64 commented Sep 3, 2015

Are there any news about this?

We are really happy if we could achieve this.

Our case is this.
We have a post.
A post has elements. Each element has an object, which can have any type.

For example:
Post ==> Element == object ==> Picture
==> Element == object ==> Video
==> Element == object ==> Movie
... and so on ...

So what we have to do is that we create models like picture, video etc. and make them inherit from the "object" model. So we can write:

Element.js

attributes:
    object: { 
        model: 'object'
    }
}

Object.js

attributes: {
    created_at: 'date',
    created_by::{
         model: 'user'
    }
}

Video.js

parentClass: 'object',
attributes: {
    length: 'float',
    title: 'string'
}

So now should be able to create a video and add it as an object to the element.

We were first trying to implement this functionality in our adapter, but the idea behind sailsjs is

@sailsbot
Copy link

sailsbot commented Oct 4, 2015

Thanks for posting, @DavidRivera. I'm a repo bot-- nice to meet you!

It has been 30 days since there have been any updates or new comments on this page. If this issue has been resolved, feel free to disregard the rest of this message. On the other hand, if you are still waiting on a patch, please:

  • review our contribution guide to make sure this submission meets our criteria (only verified bugs with documented features, please; no questions, commentary, or bug reports about undocumented features or unofficial plugins)
  • create a new issue with the latest information, including updated version details with error messages, failing tests, and a link back to the original issue. This allows GitHub to automatically create a back-reference for future visitors arriving from search engines.

Thanks so much for your help!

@sailsbot sailsbot closed this as completed Oct 4, 2015
@smyth64
Copy link

smyth64 commented Oct 4, 2015

We must find a solution here, this is an important feature!

@devinivy
Copy link

devinivy commented Oct 4, 2015

Since @particlebanana indicated that it's a valid feature request, I'm reopening until someone migrates it into the roadmap with a PR.

@devinivy devinivy reopened this Oct 4, 2015
@sailsbot
Copy link

sailsbot commented Nov 4, 2015

Thanks for posting, @DavidRivera. I'm a repo bot-- nice to meet you!

It has been 30 days since there have been any updates or new comments on this page. If this issue has been resolved, feel free to disregard the rest of this message. On the other hand, if you are still waiting on a patch, please:

  • review our contribution guide to make sure this submission meets our criteria (only verified bugs with documented features, please; no questions, commentary, or bug reports about undocumented features or unofficial plugins)
  • create a new issue with the latest information, including updated version details with error messages, failing tests, and a link back to the original issue. This allows GitHub to automatically create a back-reference for future visitors arriving from search engines.

Thanks so much for your help!

@sailsbot sailsbot closed this as completed Nov 4, 2015
@didil
Copy link

didil commented Dec 16, 2015

any idea if this is going to be implemetend ?

@robbyoconnor
Copy link

This is a joke that this STILL hasn't been implemented

@devinivy
Copy link

@robbyoconnor waterline is open-source and I'm sure many would be pumped to have this, so feel free to spec, implement, and/or write tests for this feature.

@robbyoconnor
Copy link

@devinivy that wasn't supposed to come off so demanding -- just seems all development around sails is dead....I completely agree -- I just don't have the experience to implement it properly!

@kevinburkeshyp
Copy link

it came off as very demanding. "This is a joke" for a bunch of people who work on the project for free.

-kevin

On Feb 29, 2016, at 09:53, robbyoconnor notifications@github.com wrote:

@devinivy that wasn't supposed to come off so demanding -- just seems all development around sails is dead....


Reply to this email directly or view it on GitHub.

@kevinburkeshyp
Copy link

It's really not acceptable to talk to the maintainers like that. You wouldn't talk like that in person so don't do it here.

-kevin

On Feb 29, 2016, at 09:53, robbyoconnor notifications@github.com wrote:

@devinivy that wasn't supposed to come off so demanding -- just seems all development around sails is dead....


Reply to this email directly or view it on GitHub.

@robbyoconnor
Copy link

My apologies <3 - Just frustrated with the lack of maintenance...I do understand time constraints and free time lacking. ❤️

@kevinob11
Copy link

@robbyoconnor I similarly didn't feel like I had the experience to add this to waterline, but desperately wanted it and other features. Thankfully Sails allows you to implement your own ORM if you want to! There are already hooks written for sequelize and I wrote one for bookshelf myself. Lots of options even if you don't feel you have the experience to contribute to waterline. Also the only way you are going to get the experience is jumping in and trying to help!

@robbyoconnor
Copy link

Wait, there are hooks for sequelize?

@robbyoconnor
Copy link

@kevinob11, Found it

@robbyoconnor
Copy link

@kevinob11
Copy link

@robbyoconnor and here is my attempt at bookshelf, of note it is super opinionated toward my current project, we may clean that up at the end of the project and share it more widely.

Also sorry if discussing alternatives in a project's issue queue isn't appropriate.

@emahuni
Copy link

emahuni commented Jul 22, 2018

any news on this?
I see strapi that uses waterline has polymorphic orm implemented. i don't understand why this doesnt have it. it seems like the guys at strapi worked a lot on the orm, there is a lot that was put on top. maybe we could borrow code from there, just my thought

@emahuni
Copy link

emahuni commented Jul 27, 2018

I have a bit of code written that does it without modifying the core code. It creates the relations on the polymorphic model and the related ones. I grepped thru strapi code and i couldn't pin down how they are doing it. I managed to get a few ideas out of what i saw though. Need to make it a hook and publish it on github and npm once done. maybe waterline can borrow that code and incorp it into the core for support. I am a less-than-two-weeks old sails user so the code maybe silly on certain implementations, but it gets the job done. This just shows how simple sails is, though it works.

I am mentioning Strapi a lot coz a few weeks ago i learnt about it coming from feathersjs. I ran from feathersJs for many reasons, then found Strapi. Strapi lacked other things such as self-documenting in models and their documentation of things is poor as well. They mentioned waterline in there and I found sails to do exactly what I wanted with a few exceptions that strapi is actually good at right now such as this.

In a nutshell the hook does this:

  1. it goes thru all models, just after they are read from the fs by the module loader's loadModels, and tries to find association attributes with a * instead of a model. eg: related: { collection: "*"} instead of related: {collection: "person"}. the asterix means this is a polymorphic association, it doesn't know what model this record might be associated with.
  2. then it finds the inverse of the models that are pointing to that model's attrib key ie: related in this eg. But i made it variable.
  3. it then creates attributes that have normal sails associations based on this information so that waterline just works without modifying anything.
  4. deletes the polymorphic attribute so that it doesn't crash waterline when initializing.
  5. about todo: create a findPolyPop query modifier that populates all these relationships in one go
  6. about todo: creates a getter using customToJson (since afterFind isn't ready yet), that makes it easy to group all associations' results into one dictionary since we don't know who and how many will be associated with this model. the group key is the variable key name deleted earlier during init in this case related
  7. about todo: delete the actual funny results keys of the polymorphic associations so that the results obj is clean
  8. boom we have polymorphic model.

The whole implementation is abstracted from how strapi polymorphic associations work.
I couldn't find exactly how they are doing it so i just tossed everything and implemented it myself.

If there is any work being done on polymorphic point me to it, I want to help coz this a feature that's long overdue and very very essential to waterline. It was almost a deal breaker for me since what i want to do has complex associations that may actually make it impractical to write all associations declaratively. I had to pull hairs and implement it myself until waterline supports or use its code.

@emahuni
Copy link

emahuni commented Jul 29, 2018

ok I have finished the first working draft and published to npm and github:
https://www.npmjs.com/package/sails-hook-et-polymorphic-orm
https://github.com/emahuni/sails-hook-et-polymorphic-orm

I will refine the README, was in a hurry when i wrote it. Tests should show you most of the usage.

(Edited): There was an unexpected issue loading the hook before sails-hook-orm. I had to rename the hook to sails-hook-et-polymorphic-orm from sails-hook-polymorphic-orm this is a trick i figured out to load the hook before orm.

@johnabrams7 johnabrams7 transferred this issue from balderdashy/waterline May 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests