# Connecting a row of an unknown table to another row of an un

**URL:** <https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285>\
**Category:** Rails\
**Created:** [September 23, 2007, 4:04am UTC](https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285 "2007-09-23T04:04:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mcmire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/f17d59/32.png) [@mcmire](https://www.ruby-forum.com/u/mcmire)\
**Post date:** [September 23, 2007, 4:04am UTC](https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285/1 "2007-09-23T04:04:32Z")

</div>

Hello all,

I’m currently designing a web app in Rails that lets me keep a directory  
of free/opensource computer games. Each game has attributes like name,  
website, review, etc., but each game can also be associated with a set  
of genres and gameplay elements. The main three tables I’m working with  
are “games”, “genres”, “elements”, “game\_genres”, and “game\_elements”  
(the last two being join tables, obviously). The models look like

class Game \< ActiveRecord::Base  
has\_many :game\_genres  
has\_many :genres, :through =\> :game\_genres  
has\_many :game\_elements  
has\_many :elements, :through =\> :game\_elements  
end  
class Genre \< ActiveRecord::Base  
has\_many :game\_genres  
has\_many :games, :through =\> :game\_genres  
end  
class Element \< ActiveRecord::Base  
has\_many :game\_elements  
has\_many :games, :through =\> :game\_elements  
end  
class GameGenre  
belongs\_to :game  
belongs\_to :genre  
end  
class GameElement  
belongs\_to :game  
belongs\_to :element  
end

So I’ve got those associations down pat (although, yes, I realize I  
probably could have used habtm). Here comes the hard part. As well as  
joining multiple genres and multiple elements to multiple games, I’d  
also like to be able to join one genre to multiple genres, one element  
to multiple elements, and multiple genres to multiple elements.  
Visually speaking, instead of being able to do just this:

element - game ----- genre  
element -. .´ game \ / genre  
element X— game X genre  
element / `-- game /`- genre  
element / game - genre

I’d like to be able to do this:

.-----------------------------------.  
/’- element - game ----- genre -’  
/ .- element -. .´ game \ / genre —.  
\ ‘- element X— game X genre —|  
`-- element /`– game / `- genre -. |  
.- element / game ´ genre -|-’  
‘-----------------------------------’

My first idea was to create three extra join tables, “genre\_genres”,  
“element\_elements”, and “genre\_elements”. I realized, however, that I  
could collapse that into one “connections” table:

id :integer  
a\_id :integer  
b\_id :integer  
a\_class\_name :string  
b\_class\_name :string

The \_id’s can hold either/both the id of a genre or an element; likewise  
the \_class\_name’s can hold either/both “genre” or “element”.

However, that would require hacking together a custom ActiveRecord class  
that created relations given a table in the format I described, and I  
thought, surely there’s already something out there that does this?

Then I realized that my unified join table vaguely resembled something I  
remembered reading about in the Agile Web D. using Rails book I  
picked up not too long ago: polymorphic associations. Intrigued, I  
looked around on the web for a while and found a plugin  
“has\_many\_polymorphs”. I’m not sure if this is what I should use though.

Could someone give me some pointers on how to pull this trick off?  
Thanks in advance.

– Elliot W.

---

<div class="post-metadata">

**Author:** ![mcmire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/f17d59/32.png) [@mcmire](https://www.ruby-forum.com/u/mcmire)\
**Post date:** [September 23, 2007, 4:06am UTC](https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285/2 "2007-09-23T04:06:33Z")

</div>

On 09/22/2007 09:02 PM, Elliot W. wrote:  
[…]

> class GameGenre  
> belongs\_to :game  
> belongs\_to :genre  
> end  
> class GameElement  
> belongs\_to :game  
> belongs\_to :element  
> end

Sorry, that’s supposed to be:

class GameGenre \< ActiveRecord::Base  
belongs\_to :game  
belongs\_to :genre  
end  
class GameElement \< ActiveRecord::Base  
belongs\_to :game  
belongs\_to :element  
end

– Elliot

---

<div class="post-metadata">

**Author:** ![mcmire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/f17d59/32.png) [@mcmire](https://www.ruby-forum.com/u/mcmire)\
**Post date:** [September 23, 2007, 10:53pm UTC](https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285/3 "2007-09-23T22:53:55Z")

</div>

Okay. I’ve checked out has\_many\_polymorphs and it does seem like it fits  
in this situation. So now I’ve come to this point:

class Association \< ActiveRecord::Base  
belongs\_to :left, :polymorphic =\> true  
belongs\_to :right, :polymorphic =\> true

acts\_as\_double\_polymorphic\_join(  
:lefts =\> [:genres, :elements],  
:rights =\> [:genres, :elements]  
)  
end

And table “associations”:

left\_id :integer  
left\_type :string  
right\_id :integer  
right\_type :string

That’s great, I’ll be able do stuff like:

g = Genre.find(1)  
g.lefts.map(&:class) #=\> [Genre, Genre, Element, Genre, …]  
g.rights.map(&:class) #=\> [Element, Genre, …]  
g.genres.map(&:name) #=\> [‘Action’, ‘Arcade’, …]  
g.elements(&:name) #=\> [‘First-Person View’, ‘Jumping’, …]  
e = Element.find(1)

# etc…

However, now I foresee a problem. If I tried to do this:

g.genres \<\< Genre.find(2)

since both lefts and rights can contain Genres, which collection would  
the new Genre go into?

But you know, I don’t care so much being able to access both lefts and  
rights – ideally what would be needed is just this:

g.associated.map(&:class) #=\> [Genre, Element, Genre, Genre, Element,  
…]

That should essentially find every genre and element whose id ==  
associations.right\_id (if associations.left\_id == g.id) or whose id ==  
associations.left\_id (if associations.right\_id == g.id), and return the  
objects corresponding to those ids.

Ugh. This does not look easy 🙂 Ideas, anyone?

– Elliot

---

<div class="post-metadata">

**Author:** ![mcmire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/f17d59/32.png) [@mcmire](https://www.ruby-forum.com/u/mcmire)\
**Post date:** [October 30, 2007, 10:18am UTC](https://www.ruby-forum.com/t/connecting-a-row-of-an-unknown-table-to-another-row-of-an-un/115285/4 "2007-10-30T10:18:31Z")

</div>

Hi. I have a problem with acts\_as\_double\_polymorphic\_join …

I put an example from script/console:

> > i=Image.find 1  
> > =\> #\<Image:0xb76fe41c @attributes={“href”=\>nil, “id”=\>“1”}
> 
> > i.links.map(&:id)  
> > =\> [1, 2, 3, 4, 5, 6]
> 
> > i.links \<\< Link.create  
> > =\> …
> 
> > i.links.map(&:id)  
> > =\> [1, 2, 3, 4, 5, 6]
> 
> > i.reload  
> > =\> …
> 
> > i.links.map(&:id)  
> > =\> [1, 2, 3, 4, 5, 6, 7]

i.links doesn’t update his values automaticaly. But if I use  
i.related\_tos (plural of related\_to) in spite of i.links it works  
perfectly…

example: (include related links and images…)

> > i=Image.find 1  
> > =\> #\<Image:0xb764e634 @attributes={“href”=\>nil, “id”=\>“1”}
> 
> > i.related\_tos.map(&:id)  
> > =\> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8]
> 
> > i.links \<\< Link.create  
> > =\> …
> 
> > i.related\_tos.map(&:id)  
> > =\> [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]

Any idea?
