# Abstracted associations?

**URL:** <https://www.ruby-forum.com/t/abstracted-associations/140217>\
**Category:** Rails\
**Created:** [June 12, 2008, 12:38am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217 "2008-06-12T00:38:47Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 12:38am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/1 "2008-06-12T00:38:47Z")

</div>

I have a case where an association needs to be abstracted. It happens  
to be a has\_one.

The parent will always have a has\_one association, but the exact  
model/table that should point to will change based on value available  
from the controller. So, it’s a parameter I can feed to  
ParentModel.new()

I haven’t been able to find any references to doing that. Does Rails  
allow for this, can it be hacked? Would Rails have a different  
opinion as to how that need should be handled?

– gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 1:08am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/2 "2008-06-12T01:08:18Z")

</div>

By an association that needs to be abstracted, do you mean a polymorphic  
association?

– Josh

Greg W. wrote:

> I have a case where an association needs to be abstracted. It happens  
> to be a has\_one.
> 
> The parent will always have a has\_one association, but the exact  
> model/table that should point to will change based on value available  
> from the controller. So, it’s a parameter I can feed to  
> ParentModel.new()
> 
> I haven’t been able to find any references to doing that. Does Rails  
> allow for this, can it be hacked? Would Rails have a different  
> opinion as to how that need should be handled?
> 
> – gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 1:18am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/3 "2008-06-12T01:18:52Z")

</div>

> > allow for this, can it be hacked? Would Rails have a different  
> > opinion as to how that need should be handled?

On Jun 11, 2008, at 4:08 PM, Joshua A. wrote:

> By an association that needs to be abstracted, do you mean a  
> polymorphic  
> association?

Hmm. Dunno. Will read up on that, but meanhwile, what I’m doing is  
something akin to this:

class Vehicle \< AR::Base  
has\_one :engine  
end

class Engine \< AR::Base  
belongs\_to :vehicle  
end

But… I need Engine to be JetEngine, TurboFanEngine, PistonEngine –  
all engines, but with completely different attributes from each other.

So, yes, generically, this could be polymorphic classes. Outside of  
AR CRUD, they’ll have little in common. It remains to be seen how  
many class-specific methods each might have.

So, yeah, I’m trying to figure out where Rails wants to handle this–  
inside Vehicle, or inside Engine.

– gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 1:32am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/4 "2008-06-12T01:32:53Z")

</div>

For what you’re saying, it doesn’t really sound like you’re looking for  
polymorphism. Polymorphism would be where you have an object that can  
belong to many different objects. (Like Comment could be associated to a  
BlogPost, an Article, a Message, etc).

It sounds like you’re looking for STI. So you would define your base  
class Engine, and subclass the other \*Engine classes out of that. Shared  
methods could simply be placed in the Engine model, making those methods  
available to it’s subclasses, and then a method specific to JetEngine  
only could be put in the JetEngine class.

This page is helpful with how STI would work:  
[http://wiki.rubyonrails.org/rails/pages/singletableinheritance](http://wiki.rubyonrails.org/rails/pages/singletableinheritance)

– Josh

Greg W. wrote:

> > > allow for this, can it be hacked? Would Rails have a different  
> > > opinion as to how that need should be handled?
> 
> On Jun 11, 2008, at 4:08 PM, Joshua A. wrote:
> 
> > By an association that needs to be abstracted, do you mean a  
> > polymorphic  
> > association?
> 
> Hmm. Dunno. Will read up on that, but meanhwile, what I’m doing is  
> something akin to this:
> 
> class Vehicle \< AR::Base  
> has\_one :engine  
> end
> 
> class Engine \< AR::Base  
> belongs\_to :vehicle  
> end
> 
> But… I need Engine to be JetEngine, TurboFanEngine, PistonEngine –  
> all engines, but with completely different attributes from each other.
> 
> So, yes, generically, this could be polymorphic classes. Outside of  
> AR CRUD, they’ll have little in common. It remains to be seen how  
> many class-specific methods each might have.
> 
> So, yeah, I’m trying to figure out where Rails wants to handle this–  
> inside Vehicle, or inside Engine.
> 
> – gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 4:14am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/5 "2008-06-12T04:14:35Z")

</div>

> Greg W. wrote:

> > opinion  
> > end  
> > inside Vehicle, or inside Engine.  
> > Joshua A. wrote:  
> > It sounds like you’re looking for STI.

Mmm. I don’t believe so. The data are completely different for each  
engine class. In cases where there’s a lot of similar data and a few  
fields exclusive to each “type” then, I’m willing to bunch them  
together in a shared table and derive records/classes by type field,  
but for this case, the tables share very few fields and should be  
independent.

– gw

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 9:53am UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/6 "2008-06-12T09:53:31Z")

</div>

On Jun 12, 2:59 am, Greg W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Mmm. I don’t believe so. The data are completely different for each  
> engine class. In cases where there’s a lot of similar data and a few  
> fields exclusive to each “type” then, I’m willing to bunch them  
> together in a shared table and derive records/classes by type field,  
> but for this case, the tables share very few fields and should be  
> independent.

I assume more than one vehicle could have the same engine, so did you  
mean  
class Vehicle \< AR::Base  
belongs\_to :engine  
end

class Engine \< AR::Base  
has\_one :vehicle  
end

if so, then a polymorpic association could do the trick: then change  
the belongs\_to to belongs\_to :engine, :polymorphic =\> true  
and the has\_one to has\_one vehicle, :as =\> :engine.

Then when you to foo.engine = some\_jet\_engine then engine\_id will be  
be set appropriately and engine\_type will be set to JetEngine

Fred

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 5:12pm UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/7 "2008-06-12T17:12:30Z")

</div>

Once again–what Fred said. 😉 Look into polymorphic associations. If  
I understand it right, you put profile\_id and profile\_type fields in  
your users table. profile\_type is what tells AR which table to go to  
for a given user’s profile.

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [June 12, 2008, 12:49pm UTC](https://www.ruby-forum.com/t/abstracted-associations/140217/8 "2008-06-12T12:49:50Z")

</div>

On Jun 12, 2008, at 12:46 AM, Frederick C. wrote:

> On Jun 12, 2:59 am, Greg W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Mmm. I don’t believe so. The data are completely different for each  
> > engine class. In cases where there’s a lot of similar data and a few  
> > fields exclusive to each “type” then, I’m willing to bunch them  
> > together in a shared table and derive records/classes by type field,  
> > but for this case, the tables share very few fields and should be  
> > independent.
> 
> I assume more than one vehicle could have the same engine,

In this case, no. At least, not how I interpret the question. I guess  
I’ll just spell it out (at the risk of invoking sidebar questions).

PrivilegedUser (authentication details only)  
has\_one profile  
has\_many privileges  
has\_many filters

Profile (remainder of a user’s “description”)  
(set\_table\_name = x or y or z)  
belongs\_to privileged\_user

Privilege (1 record per privilege)  
belongs\_to privileged\_user

Filter (1 record per data access filter definition)  
belongs\_to privileged\_user

Any one PrivilegedUser table record will be associated with one, and  
only one, of the Profile tables, and only one record in that Profile  
table. Any entry in the Profile table will be associated with one,  
and only one, of the PrivilegedUser table records. At any one time  
there is only ever one instance of a PrivilegedUser being used per  
request – that being the logged in user.

This is for a group of applications where some of them have multiple  
user models in which profile details for one type of user is very  
different than another. Simple apps will need only one Profile,  
complex apps can have several. Profile tables could have a handful of  
fields or dozens of fields–of which none may be common, so it just  
doesn’t make sense to use a single table. (Think doctors & patients,  
teachers & students – both sharing the same login system, but vastly  
different user profiles because they use the app in very different  
ways).

I have used this system for quite some time already. The methodology  
is sound (and it’s 90% written in Rails already), I’m just trying to  
figure out how to Railsify this and one other implementation detail.

At first I was wondering whether to try to handle it in  
PrivilegedUser or Profile, but the more I think about it, if it is  
possible to parameterize the has\_one declaration in PrivilegedUser, I  
think that’s what I’m looking for (which is how I handled it before),  
and I’ll end up with a unique model per specific Profile (probably  
sub-classed ones, so I can consolidate common methods).

– gw
