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
end

class Surveys …
belongs_to :company
has_many :survey_questions
end

class SurveyQuestions …
belongs_to :survey
has_many :survey_answers
end

class SurveyAnswers …
belongs_to :survey_question
end

Thanks in advance for any help.

Cheers,
Chad

On Thu, Mar 5, 2009 at 9:21 AM, Chad [email protected] wrote:

 has_many :survey_questions
end

class SurveyQuestions …
 belongs_to :survey
 has_many :survey_answers
end

class SurveyAnswers …
 belongs_to :survey_question
end

What happens when you try:

(1) @company.surveys.survey_questions.survey_answers

or

(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.

HTH,

Peter

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
array.

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

On Mar 5, 1:13 am, Peter V.

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…

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.

2009/3/5 Chad [email protected]

On Thu, Mar 5, 2009 at 10:13 AM, Peter V.
[email protected] wrote:

(1) @company.surveys.survey_questions.survey_answers

or

(2) @company.survey_questions.survey_answers

I believe form (1) should certainly work

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

Sorry for the noise it created.

Peter

If you wanted all the answers for a particular company then you could
turn
it round and find all the answers where survey_question.survey.company =
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.

2009/3/5 Chad [email protected]

Maybe the other way around…

class Company
has_many :surveys

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

Greetings,
Wojtek