Get data from has_and_belongs_to_many + has_many

I have 3 models, A, B and C
and the classic 3 relations:

  1. A <— has_and_belongs_to_many —> B

  2. B has_many C

B -> c1
-> c2
-> c3

  1. C belong_to B

C -> a1

Question:
How can I get C entries in relationship to an A entry ?

in other words, I have
a = A.find id

and I want C

I have tried
a.bs.cs (NOT correct)
A.bs.all(:include => :cs) (NOT correct)

do you have any solutions ?

thank you,
Alessandro DS

On 20 May 2010 15:00, Ale Ds [email protected] wrote:

Question:
How can I get C entries in relationship to an A entry ?

in other words, I have
a = A.find id

and I want C

You need to iterate over a’s bs [1] collection, and return the related
cs. Then probably only return uniq c records (a given c might be
linked to more than one b…)
This should give you what you want:

cs=[]
a.bs.each do |b|
cs += b.cs
end
cs.uniq!

and this is the same thing:
a.bs.inject {|cs, b| sum + b.cs }.uniq

[1] This is why convention prefers Foo/Bar for example names… “a,
b, c” doesn’t make for easy or understandable reading.

On May 20, 4:13 pm, Michael P. [email protected] wrote:

You need to iterate over a’s bs [1] collection, and return the related
cs.

I don’t think that is necessary. It should be possible to get the data
in a single sql query.
@cs = C.all(:joins => {:b => :as}, :conditions => {‘as.id = 1’})

[1] This is why convention prefers Foo/Bar for example names… “a,
b, c” doesn’t make for easy or understandable reading.

I second that

Michael P. wrote:

You need to iterate over a’s bs [1] collection, and return the related
cs. Then probably only return uniq c records (a given c might be
linked to more than one b…)
This should give you what you want:

cs=[]
a.bs.each do |b|
cs += b.cs
end
cs.uniq!
This is the solution that I don’t like to use

and this is the same thing:
a.bs.inject {|cs, b| sum + b.cs }.uniq

this looks interesting ! (even if I have to brush up ‘inject’ :slight_smile: )
but I am looking for a more simpe solution

thank you,
Alessandro DS

[1] This is why convention prefers Foo/Bar for example names… “a,
b, c” doesn’t make for easy or understandable reading.

Yes, I agree with you (the pluralization of A,B,C is unreadable)

Sharagoz wrote:
I don’t think that is necessary. It should be possible to get the data
in a single sql query.
@cs = C.all(:joins => {:b => :as}, :conditions => {‘as.id = 1’})

That 's what I was looking for,
I was wrong because I began research from the wrong side (A instead of
C)

Thank you very much,
Alessandro DS

On 20 May 2010 16:59, Sharagoz [email protected] wrote:

On May 20, 4:13 pm, Michael P. [email protected] wrote:

You need to iterate over a’s bs [1] collection, and return the related
cs.

I don’t think that is necessary. It should be possible to get the data
in a single sql query.
@cs = C.all(:joins => {:b => :as}, :conditions => {‘as.id = 1’})

If you don’t have any info apart from a_id (in params, maybe), then
yes, go query the DB in one hit. But if you already have your ‘a’
eager-loaded with all its related bs and cs, then there’s not much
sense in rebuilding a load of objects; you might as well just select
them out of the collections you have in memory.
Depends on your starting point.