Sails: Polymorphic Associations

Created on 19 Jun 2014  Â·  33Comments  Â·  Source: balderdashy/sails

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?

Most helpful comment

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 [email protected] 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.

All 33 comments

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.

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.

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

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.

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

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

+1

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

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?

any news on this?

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

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

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?

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

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!

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

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

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!

any idea if this is going to be implemetend ?

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

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

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

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 [email protected] 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.

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 [email protected] 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.

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

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

Wait, there are hooks for sequelize?

@kevinob11, Found it

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

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

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.

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.

Was this page helpful?
0 / 5 - 0 ratings