# Modeling polymorphic containment

**URL:** <https://www.ruby-forum.com/t/modeling-polymorphic-containment/141093>\
**Category:** Rails\
**Created:** [June 22, 2008, 12:08am UTC](https://www.ruby-forum.com/t/modeling-polymorphic-containment/141093 "2008-06-22T00:08:51Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![smurfherder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@smurfherder](https://www.ruby-forum.com/u/smurfherder)\
**Post date:** [June 22, 2008, 12:08am UTC](https://www.ruby-forum.com/t/modeling-polymorphic-containment/141093/1 "2008-06-22T00:08:51Z")

</div>

I need to create the equivalent of a folder system. Each folder can  
have any model placed into it, including other folders, as long as it  
is a tree (not a graph, not a partial order.)

One idea that looked good is this

class Phile  
acts\_as\_tree  
acts\_as\_list, :scope =\> :parent  
belongs\_to :philable, :polymorphic =\> true  
end

So, now I have things that are philes that I can access as a tree and  
whose kids can be handled as a list. Kewl. Because the belongs\_to is  
in the Philes class, the targets of the :phile polymorphism don’t have  
any foreign key storage requirements, which is also kewl, since I can  
refer to any model using this technique.

In something that is referred to, the “target” class, we can place a  
has\_one this way…

class Whatever  
has\_one :phile, :as =\> :philable  
end

So now I can access the phile entry.

What is missing is this: I want to

```
* issue a find to an instance of a whatever,
* use the various scopes of the phile associated with that

```

instance to restrict the search  
- this means things like direct\_children, descendants,  
full\_… etc.  
\* have the conditions in the find apply to the Whatever, not the  
phile fields.

Trying to figure this out has made my head hurt right down to my  
spleen.

I am willing to restrict the search to specific models, although it  
really shouldn’t matter as long as the fields referenced in conditions  
are present in all the models.

Using :include doesn’t seem to work through polymorph associations.  
The only thing I can think of is something like this:

def alt\_find(target\_class,relationship,\*args)  
target\_class.with\_scope( :find =\> { :conditions =\>  
{ target\_object.philable.send(relationship)) } }) do  
target\_class.find(\*args)  
end  
end

This requires that one specify a single target class in a folder, and  
takes the relationship like :direct\_children  
as a parameter. It seems like this should be easier in Rails somehow,  
with some magic proxy class or some such. I have looked around to see  
if I can find something like this, but can’t seem to find it (although  
the impenetrable acts\_as\_taggable might be close.)

Anyone know an easier way to do this kind of thing? Ideally, there  
would be a way to tell ActiveRecord that some other object is  
responsible for implementing an association for you. With that, one  
could say things like

```
folder.direct_children.find(:all, ...)

```

Instead of

folder.find(Philes.find(w.phile).children.map(&:philable\_id), …)

Alternately, is there an implementation of acts\_as\_tree or others in  
that ilk for which the scoping methods like direct\_children, etc., all  
of whom take parameters that are then passed to find(), can have the  
target of the find not be the tree itself but the the polymorphic  
targets instead?

Or, can we simply get “include” to work through polymorphic  
associations, returning rows that look like STI or other include  
results, only including all the various models contained? This would  
require only an addition query to get the :philable\_type of each  
member in the Philable table that are in scope – the rest could be a  
SQL query performed on the back end, just as is done for :included  
associations or STI.

Any help appreciated!

-ns
