简体   繁体   中英

Rails or SQL to get through a few model associations

I'm a bit of a n00b when it comes to hacking my own SQL for my ruby on rails app, so your help would be much appreciated. I have a model as follows:

Timetable 
    has_many :enrollments

Enrollment 
    belongs_to :timetable 
    belongs_to :stream 
    has_one :course, :through => stream
    #Stream & Timetable together are unique for an Enrollment

Stream 
    has_many :enrollments 
    belongs_to :course

Course 
    has_many :streams

ie

Timetable 1-* Enrollments *-1 Stream *-1 Course

I'm trying to find the best way to get a set of courses associated with a timetable, through it's enrollments, through each enrollment's streams, which have a course.

Preferably something like:

Timetable.courses

Trying the following had no luck

Timetable
    has_many :courses, :through => :enrollments, :source => :course

It gave me an error ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_one :through for has_many :courses, :through => :enrollments. Use :source to specify the source reflection. ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_one :through for has_many :courses, :through => :enrollments. Use :source to specify the source reflection.

I took a look at Invalid source reflection macro :has_many :through and it seemed to be pretty close.

I also found http://code.alexreisner.com/articles/has-many-through-habtm.html but I can't quite grasp how to apply this here (although it is 12am NZT, so maybe that's why!).

Help, hints or even the answer would be great!

If I understand correctly, this is the SQL you want (for example):

SELECT c.*
FROM courses c
  LEFT JOIN streams s ON s.course_id = c.id
  LEFT JOIN enrollments e ON e.stream_id = s.id
  LEFT JOIN timetables t ON e.timetable_id = t.id
WHERE t.id = 5

To achieve this in rails, have a look at

Course.joins(:streams => {:enrollments => :timetables}).to_sql

This shows you the sql it generates. You can then apply other conditions like so

Course.joins(:streams => {:enrollments => :timetables}).where(some condition on timetables)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM