Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Many to many polymorphic relationships

See comments for updates.

I've been struggling to get a clear and straight-forward answer on this one, I'm hoping this time I'll get it! :D I definitely have a lot to learn still with Rails, however I do understand the problem I'm facing and would really appreciate additional help.

  • I have a model called "Task".
  • I have an abstract model called "Target".
  • I would like to relate multiple instances of subclasses of Target to Task.
  • I am not using single table inheritance.
  • I would like to query the polymorphic relationship to return a mixed result set of subclasses of Target.
  • I would like to query individual instances of subclasses of Target to obtain tasks that they are in a relationship with.

So, I figure a polymorphic many to many relationship between Tasks and subclasses of Targets is in order. In more detail, I will be able to do things like this in the console (and of course elsewhere):

task = Task.find(1) task.targets [...array of all the subclasses of Target here...] 

But! Assuming models "Store", "Software", "Office", "Vehicle", which are all subclasses of "Target" exist, it would be nice to also traverse the relationship in the other direction:

store = Store.find(1) store.tasks [...array of all the Tasks this Store is related to...] software = Software.find(18) software.tasks [...array of all the Tasks this Software is related to...] 

The database tables implied by polymorphic relationships appears to be capable of doing this traversal, but I see some recurring themes in trying to find an answer which to me defeat the spirit of polymorphic relationships:

  • Using my example still, people appear to want to define Store, Software, Office, Vehicle in Task, which we can tell right away isn't a polymorphic relationship as it only returns one type of model.
  • Similar to the last point, people still want to define Store, Software, Office and Vehicle in Task in one way shape or form. The important bit here is that the relationship is blind to the subclassing. My polymorphs will initially only be interacted with as Targets, not as their individual subclass types. Defining each subclass in Task again starts to eat away at the purpose of the polymorphic relationship.
  • I see that a model for the join table might be in order, that seems somewhat correct to me except that it adds some complexity I assumed Rails would be willing to do away with. I plea inexperience on this one.

It seems to be a small hole in either rails functionality or the collective community knowledge. So hopefully stackoverflow can chronicle my search for the answer!

Thanks to everyone who help!

like image 289
Alexander Trauzzi Avatar asked Jul 14 '09 22:07

Alexander Trauzzi


People also ask

Is polymorphism is many to many relationship?

A polymorphic relationship is used when you want something like Many to Many relationship, but without having to create extra tables every time you want to add a new Model to the mix. Polymorphic helps you combine all the junction tables into 1 very slim table, but at a cost.

What is a polymorphic relationship Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

What is difference between Has_one and Belongs_to?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user .

Does Rails have one relationship?

Ruby on Rails ActiveRecord Associations has_oneA has_one association sets up a one-to-one connection with another model, but with different semantics. This association indicates that each instance of a model contains or possesses one instance of another model.


1 Answers

You can combine polymorphism and has_many :through to get a flexible mapping:

class Assignment < ActiveRecord::Base   belongs_to :task   belongs_to :target, :polymorphic => true end  class Task < ActiveRecord::Base   has_many :targets, :through => :assignment end  class Store < ActiveRecord::Base   has_many :tasks, :through => :assignment, :as => :target end  class Vehicle < ActiveRecord::Base   has_many :tasks, :through => :assignment, :as => :target end 

...And so forth.

like image 116
SFEley Avatar answered Sep 27 '22 20:09

SFEley