Model has_many 3 degrees separation

I feel like this should be simple but it's stumping me.

In the following model, is there an easy way to setup my models so
that I can make the following call: @company.survey_answers

class Company < ActiveRecord::Base
  has_many :surveys
  has_many :survey_questions, :through => :surveys

class Surveys ...
  belongs_to :company
  has_many :survey_questions

class SurveyQuestions ...
  belongs_to :survey
  has_many :survey_answers

class SurveyAnswers ...
  belongs_to :survey_question

Thanks in advance for any help.


What happens when you try:

(1) @company.surveys.survey_questions.survey_answers


(2) @company.survey_questions.survey_answers

I believe form (1) should certainly work after removing the line
'has_many :survey_questions, :through => :surveys'

I am uncertain if form (2) will work (because I am uncertain if
has_many :through works that way and no
time to test it here)

I don't see how '@company.survey_answers' could work since there is no has_many
relationship with the name 'survey_answers' in the Company class. It
is only defined
in the SurveyQuestions class.



I like the idea, but this is what I get:

@answers = @company.surveys.survey_questions.survey_answers

undefined method `survey_questions' for #<Class:0x203b590>

I feel like the first call, @company.surveys is just returning an
array and then I'm trying to call the survey_questions method on that

Is there a way to modify that call to get the desired chaining?

As you say @company.surveys returns an array of Surveys, so normally you would have to say @company.surveys[i].survey_questions which will again return an array of questions, and so on. Are you asking for a means to automatically combine all the results obtained by iterating each of the arrays down the chain? I don’t know of a way to do that automatically, without iterating each of the arrays and building a combined list. I would not be in the least surprised to find that Ruby has some magic construct to achieve this however. Maybe this is a challenge to the Ruby geeks to provide the answer by the most concise (and possibly undecipherable) code.

Ya I agree with you - I can manually combine arrays no problem, but
then it's a pain to sort and I'm unable to use named_scope's, etc.

There's got to be a clean way...

OK, that was stupid of me to post without testing first.

Sorry for the noise it created.


If you wanted all the answers for a particular company then you could turn it round and find all the answers where = the_company. But if you followed this route for all companies you would still have the problem of grouping the answers by company which is probably no better.

Maybe the other way around...

class Company
  has_many :surveys

  def survey_answers
    SurveyAnswer.all(:joins => {:survey_question => {:survey
=> :company}},
                     :conditions => [' = :company_id',
{:company_id => id}])