# Model has\_many 3 degrees separation

**URL:** <https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048>\
**Category:** Rails\
**Created:** [March 5, 2009, 9:22am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048 "2009-03-05T09:22:13Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 9:22am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/1 "2009-03-05T09:22:13Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 10:14am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/2 "2009-03-05T10:14:25Z")

</div>

On Thu, Mar 5, 2009 at 9:21 AM, Chad [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 10:31am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/3 "2009-03-05T10:31:30Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 11:37am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/4 "2009-03-05T11:37:21Z")

</div>

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…

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 10:49am UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/5 "2009-03-05T10:49:44Z")

</div>

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 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 12:02pm UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/6 "2009-03-05T12:02:39Z")

</div>

On Thu, Mar 5, 2009 at 10:13 AM, Peter V.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 1:00pm UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/7 "2009-03-05T13:00:51Z")

</div>

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 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Chad](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecccb3/32.png) [@Chad](https://www.ruby-forum.com/u/Chad)\
**Post date:** [March 5, 2009, 4:34pm UTC](https://www.ruby-forum.com/t/model-has-many-3-degrees-separation/162048/8 "2009-03-05T16:34:52Z")

</div>

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
