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.