# Best Practice/Associations Question

**URL:** <https://www.ruby-forum.com/t/best-practice-associations-question/132106>\
**Category:** Rails\
**Created:** [March 17, 2008, 2:50am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106 "2008-03-17T02:50:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 2:50am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/1 "2008-03-17T02:50:19Z")

</div>

What is the best way to solve this problem:  
If you have a model - say Vote, and there are votes for various  
categories of things such as comments, links, etc: What is the best  
way to implement this? Is it best to create a model/database for each  
type of vote (comment\_votes, news\_votes, etc\_votes), tag each vote  
with a vote\_type parameter, or maybe do something with polymorphism.  
Additionally how does that implementation affect how would you go  
about saying something like user.comment\_votes or user.news\_votes the  
user has\_many of each of these types. I hope that makes sense and  
thanks for your ideas.

John Brunsfeld

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 3:12am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/2 "2008-03-17T03:12:35Z")

</div>

When you say “votes for various categories”, if each of your different  
categories are implemented as models, you can use single table  
inheritance  
and polymorphic associations.  
So you’d have one table, “votes” and you’d link your models using the  
following structure:

class Vote \< AR::Base  
belongs\_to :voteable, :polymorphic =\> true  
end

class Comment \< AR::Base  
has\_many : votes, :as =\> : voteable  
end

class Product \< AR::Base  
has\_many : votes, :as =\> : voteable  
end

etc

then you can do comment.votes or product.votes.

Adam

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 3:17am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/3 "2008-03-17T03:17:10Z")

</div>

Jables wrote:

> What is the best way to solve this problem:  
> If you have a model - say Vote, and there are votes for various  
> categories of things such as comments, links, etc: What is the best  
> way to implement this? Is it best to create a model/database for each  
> type of vote (comment\_votes, news\_votes, etc\_votes), tag each vote  
> with a vote\_type parameter, or maybe do something with polymorphism.  
> Additionally how does that implementation affect how would you go  
> about saying something like user.comment\_votes or user.news\_votes the  
> user has\_many of each of these types. I hope that makes sense and  
> thanks for your ideas.
> 
> John Brunsfeld

This seems to me to be a little muddy. I suggest that you start with  
what you are voting on, say an issue or better yet a proposal. Then you  
have a voter model, and finally a ballot model. So a particular voter’s  
ballot is related to a specific proposal.

Thus:

Class Voter \< ActiveRecord::Base

has\_many :ballots

Class Proposal \< ActiveRecord::Base

has\_many :ballots

Class Ballot \< ActiveRecord::Base

belongs\_to :voter  
belongs\_to :proposal

The voter model/table contains all of your identity and eligibility  
criteria. The proposal model/table contains all of the data relating to  
a specific issue, including its type or class if this is a singleton  
attribute, or you can hang a proposal\_classifications model off of  
proposals if you require N type attributes (likewise comments or notes).  
The ballot contains the voter’s choice on the issue plus whatever  
ancillary data you desire (date and time cast, method of voting, place  
of voting, ip address, etc.)

You validate the uniqueness of a ballot (one per voter per proposal) in  
the Ballot model.

HTH

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 3:26am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/4 "2008-03-17T03:26:40Z")

</div>

This is what I was thinking Adam, do you know if this is an efficient  
way to do this as the votes table starts to grow?

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 5:25am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/5 "2008-03-17T05:25:48Z")

</div>

I’m sure splitting it up into separate tables would be more efficient,  
especially if, for example, you had a class which has very few votes,  
considering you’d still need to scan through a table with a large number  
of  
records to return the given results, versus the smaller table lookup  
which  
could be achieved had you separated the votes for this class into  
another  
table.

But then it’s much nicer to implement it this way. So it’s a trade off  
in  
terms of complexity versus efficiency (isn’t that always the case? ;-).  
I  
mean, it’s not terribly complex to implement using separate tables, but  
STI  
with polymorphism is cleaner.

I guess you could always start with the STI implementation and then  
switch  
to separate tables if you find that it’s too much of a bottleneck.

Adam

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 4:33am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/6 "2008-03-17T04:33:01Z")

</div>

Question to anyone: So if you have a polymorphic relationship such as  
Adam posted with his setup, you can say comment.votes. How can you go  
the other way and say “Vote.comment”? Is that a has\_one :comment in  
the Vote model, and if so would you also put has\_one :product?

---

<div class="post-metadata">

**Author:** ![Jables](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/58956e/32.png) [@Jables](https://www.ruby-forum.com/u/Jables)\
**Post date:** [March 17, 2008, 5:28am UTC](https://www.ruby-forum.com/t/best-practice-associations-question/132106/7 "2008-03-17T05:28:09Z")

</div>

to get the object for a vote, you’d use:  
vote.voteable

which will return the object associated with the vote (either a comment,  
product, etc)

Adam
