Re: HABTM? Questions, Answers and Votes

Justin Forder
Wed, 30 Nov 2005 13:27:24 -0000

Vincent AE Scott wrote:

> Hi there, I''m new to rails and loving it, but I''ve hit a
problem that
> I''m hoping to find an elegant solution for.  I''ve been
trawling thru
> this list and the wiki, but can''t quite find the last piece to the
> problem I''m trying to solve.
>
> I''m trying to setup a simple Polling app, you know, posing
questions and
> voting on answers.  So far i have something (this is trimmed down) like:
>
> class Question < ActiveRecord::Base
>   has_and_belongs_to_many :answers
>   has_and_belongs_to_many :votes
>   belongs_to :person
> end
>
> class Answer < ActiveRecord::Base
>   has_and_belongs_to_many :votes, :join_table =>
''questions_votes''
> end
>
> class Vote < ActiveRecord::Base
>   belongs_to :person
>   has_and_belongs_to_many :answers, :join_table =>
''questions_votes''
>   has_and_belongs_to_many :questions, :join_table =>
''questions_votes''
> end

I would have expected an answer to be for (belong to) a single question,
and a vote to be for (belong to) a single answer - in other words, I
would expect one-to-many relationships rather than many-to-many.

Your statements below about the behaviour you want support this.

regards

    Justin

>
> With the following associated join table:
>
> CREATE TABLE questions_votes (
>   question_id                     INTEGER,
>   answer_id                       INTEGER,
>   vote_id                         INTEGER
> )
>
> The above allows me to perform the following:
>
> q = Question.find_first
> a = q.answers.find_first
> v = a.votes
>
> But, if i try and go the other way, from a vote back to an answer, or
> from and answer back to a question, I am passed back an array. i.e.
>
> v.questions or v.answers or a.questions are all valid.
>
> But what i really want is the singular of the aboves, i know i could use
> find_first, but that really shouldn''t be necessary.  I understand
why
> this is happening, due to the HABTM relationship.
>
> I''ve tried using belongs_to in the child classes, which works
fine, i.e.
>
> class Answer < ActiveRecord::Base
>   belongs_to :question
>   has_and_belongs_to_many :votes, :join_table =>
''questions_votes''
> end
>
> But I''m then duplicating the foreign keys, which also
doesn''t quite seem
> the most elegant approach either.  given that the relationship already
> exists in the join table.  Would i just be better off creating a new
> method on the child classes, something like:
>
> class Answer < ActiveRecord::Base
>   has_and_belongs_to_many :votes, :join_table =>
''questions_votes''
>
>   def find_question
>     self.questions.find_first
>   end
> end
>
> It still seems like a kludge, and that the model isn''t quite
> representing that data in an accurate manner.
>
> Can you suggest a better way of achieving the above?  I''m probably
> missing something really obvious here.  Maybe i just need to create a new
> Model for the relationships?
>
>
> -vince
>
>