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

3) 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

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.

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 Pavling 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

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.